Skip to Content

Interface trong Kotlin

🎯 Mục tiêu: Hiểu Interface - contract định nghĩa hành vi chung, với default implementations, properties, và cách resolve conflicts.


💡 Interface là gì?

Interface định nghĩa “contract” - tập hợp các methods và properties mà class phải có. Nó mô tả “cái gì” (what) mà không quan tâm “như thế nào” (how).

// Định nghĩa interface interface Clickable { fun click() } // Class implement interface class Button : Clickable { override fun click() { println("Button clicked!") } } fun main() { val button = Button() button.click() // Button clicked! // Polymorphism - lưu Button như Clickable val clickable: Clickable = button clickable.click() // Button clicked! }

📝 Tại sao cần Interface?

Polymorphism - Đa hình

interface Playable { fun play() } class MusicPlayer : Playable { override fun play() = println("🎵 Playing music...") } class VideoPlayer : Playable { override fun play() = println("🎬 Playing video...") } class Game : Playable { override fun play() = println("🎮 Playing game...") } // Hàm làm việc với bất kỳ Playable nào fun startMedia(media: Playable) { print("Starting: ") media.play() } fun main() { startMedia(MusicPlayer()) // Starting: 🎵 Playing music... startMedia(VideoPlayer()) // Starting: 🎬 Playing video... startMedia(Game()) // Starting: 🎮 Playing game... }

Loose Coupling - Giảm phụ thuộc

// Bad: Tight coupling class EmailService { fun sendEmail(message: String) { /* ... */ } } class OrderProcessor { private val emailService = EmailService() // ❌ Phụ thuộc trực tiếp fun processOrder(order: Order) { emailService.sendEmail("Order confirmed") } } // Good: Loose coupling với Interface interface NotificationService { fun notify(message: String) } class EmailNotification : NotificationService { override fun notify(message: String) = println("Email: $message") } class SMSNotification : NotificationService { override fun notify(message: String) = println("SMS: $message") } class OrderProcessor(private val notifier: NotificationService) { fun processOrder(order: Order) { // Logic... notifier.notify("Order confirmed") } } fun main() { // Dễ dàng switch implementation val emailProcessor = OrderProcessor(EmailNotification()) val smsProcessor = OrderProcessor(SMSNotification()) }

🔧 Default Implementation

Interface có thể có default implementation - không bắt buộc override:

interface Clickable { fun click() // Abstract - PHẢI implement fun showOff() = println("I'm clickable!") // Default - optional override fun doubleClick() { // Cũng là default implementation click() click() } } class Button(val name: String) : Clickable { override fun click() { println("$name clicked") } // showOff() và doubleClick() đã có default, không cần override } fun main() { val button = Button("Submit") button.click() // Submit clicked button.showOff() // I'm clickable! button.doubleClick() // Submit clicked \n Submit clicked }
💡

Khác với Java < 8: Java 8+ mới có default methods. Kotlin hỗ trợ từ đầu.


📦 Interface Properties

Interface có thể có abstract properties:

interface Identifiable { val id: String // Abstract property val createdAt: Long // Abstract property // Property với default getter val displayId: String get() = "ID: $id" } class User(override val id: String) : Identifiable { override val createdAt = System.currentTimeMillis() } class Document(override val id: String) : Identifiable { override val createdAt = System.currentTimeMillis() } fun main() { val user = User("user-123") println(user.displayId) // ID: user-123 println(user.createdAt) // Timestamp }
⚠️

Interface KHÔNG có backing field: Không thể khởi tạo state trong interface.

interface Bad { val name: String = "Default" // ❌ Lỗi! Không có backing field } interface Good { val name: String // ✅ Abstract get() = "Default" // ✅ Default getter (computed, không lưu state) }

🔀 Multiple Interface Inheritance

Class có thể implement nhiều interfaces:

interface Walkable { fun walk() = println("Walking...") } interface Swimable { fun swim() = println("Swimming...") } interface Flyable { fun fly() = println("Flying...") } class Duck : Walkable, Swimable, Flyable // Implement 3 interfaces class Fish : Swimable // Chỉ implement Swimable class Penguin : Walkable, Swimable { // Không fly() } fun main() { val duck = Duck() duck.walk() // Walking... duck.swim() // Swimming... duck.fly() // Flying... }

Resolving Conflicts

Khi multiple interfaces có method cùng tên:

interface A { fun foo() = println("A.foo") fun bar() } interface B { fun foo() = println("B.foo") fun bar() = println("B.bar") } class C : A, B { // PHẢI override foo() vì conflict override fun foo() { super<A>.foo() // Gọi A.foo() super<B>.foo() // Gọi B.foo() } // PHẢI override bar() vì abstract trong A override fun bar() { super<B>.bar() // Có thể dùng default từ B } } fun main() { val c = C() c.foo() // A.foo // B.foo c.bar() // B.bar }

🏛️ Interface vs Abstract Class

FeatureInterfaceAbstract Class
State (fields)❌ Không✅ Có
Constructor❌ Không✅ Có
Multiple inheritance✅ Có❌ Không
Default implementations✅ Có✅ Có
Visibility modifiersChỉ publicTất cả
Dùng khiContract, behaviorShared base + state
// Interface - chỉ behavior, không có state interface Logger { fun log(message: String) } // Abstract class - shared implementation + state abstract class BaseLogger(protected val tag: String) { abstract fun log(message: String) protected fun formatMessage(msg: String): String { return "[$tag] ${System.currentTimeMillis()}: $msg" } } class ConsoleLogger(tag: String) : BaseLogger(tag) { override fun log(message: String) { println(formatMessage(message)) } }

🎯 Interface Delegation

Kotlin cho phép delegate interface implementation:

interface Printer { fun print(text: String) } class ConsolePrinter : Printer { override fun print(text: String) = println(text) } // Delegate Printer implementation cho consolePrinter class Logger(consolePrinter: Printer) : Printer by consolePrinter { fun logInfo(msg: String) { print("[INFO] $msg") } } fun main() { val logger = Logger(ConsolePrinter()) logger.print("Hello") // Hello (delegated) logger.logInfo("Starting") // [INFO] Starting }

🛠️ Thực hành

Bài tập: Tạo hierarchy với interfaces

// TODO: Tạo: // - interface Vehicle với properties và methods // - interface Electric với charge() // - class Car, ElectricCar, Bicycle implementing phù hợp

Lời giải:

interface Vehicle { val brand: String val maxSpeed: Int fun start() fun stop() fun info() = "$brand (max: $maxSpeed km/h)" } interface Electric { val batteryLevel: Int fun charge() fun batteryStatus() = "Battery: $batteryLevel%" } class Car( override val brand: String, override val maxSpeed: Int = 200 ) : Vehicle { override fun start() = println("$brand: Engine started 🚗") override fun stop() = println("$brand: Engine stopped") } class ElectricCar( override val brand: String, override val maxSpeed: Int = 250, override var batteryLevel: Int = 100 ) : Vehicle, Electric { override fun start() = println("$brand: Silently starting ⚡🚗") override fun stop() = println("$brand: Stopped") override fun charge() { batteryLevel = 100 println("$brand: Fully charged!") } } class Bicycle( override val brand: String, override val maxSpeed: Int = 40 ) : Vehicle { override fun start() = println("$brand: Pedaling 🚲") override fun stop() = println("$brand: Braking") } fun main() { val vehicles: List<Vehicle> = listOf( Car("Toyota"), ElectricCar("Tesla"), Bicycle("Giant") ) vehicles.forEach { vehicle -> println(vehicle.info()) vehicle.start() if (vehicle is Electric) { println(vehicle.batteryStatus()) } println() } }

📱 Trong Android

// Repository pattern interface UserRepository { suspend fun getUser(id: Long): User? suspend fun saveUser(user: User) suspend fun deleteUser(id: Long) } class NetworkUserRepository(private val api: UserApi) : UserRepository { override suspend fun getUser(id: Long) = api.fetchUser(id) override suspend fun saveUser(user: User) = api.updateUser(user) override suspend fun deleteUser(id: Long) = api.deleteUser(id) } class LocalUserRepository(private val dao: UserDao) : UserRepository { override suspend fun getUser(id: Long) = dao.findById(id) override suspend fun saveUser(user: User) = dao.insert(user) override suspend fun deleteUser(id: Long) = dao.deleteById(id) } // Callback interfaces interface OnItemClickListener<T> { fun onItemClick(item: T, position: Int) fun onItemLongClick(item: T, position: Int) = false // Default } // ViewModel interface interface LoadingState { val isLoading: Boolean val error: String? } class UserViewModel : ViewModel(), LoadingState { override var isLoading = false override var error: String? = null }

⚠️ Lưu ý quan trọng

💡

Ưu tiên Interface over Implementation:
Khi declare types, dùng interface thay vì concrete class:

// ✅ Good - flexible val list: List<String> = mutableListOf() // ❌ Avoid - tight coupling val list: MutableList<String> = mutableListOf()
⚠️

Interface methods mặc định là public:
Không thể có private methods trong interface. Dùng abstract class nếu cần.


✅ Checklist - Tự kiểm tra

Sau bài học này, bạn có thể:

  • Hiểu tại sao cần interface (polymorphism, loose coupling)
  • Tạo interface với abstract methods
  • Sử dụng default implementation
  • Tạo interface properties
  • Implement multiple interfaces
  • Resolve conflicts khi multiple inheritance
  • Phân biệt interface vs abstract class
  • Áp dụng interface delegation

Tiếp theo: Inheritance

Last updated on