📜 Interface
🎯 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ì?
Phần tiêu đề “💡 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 interfaceinterface Clickable { fun click()}
// Class implement interfaceclass 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?
Phần tiêu đề “📝 Tại sao cần Interface?”Polymorphism - Đa hình
Phần tiêu đề “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àofun 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
Phần tiêu đề “Loose Coupling - Giảm phụ thuộc”// Bad: Tight couplingclass 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 Interfaceinterface 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
Phần tiêu đề “🔧 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}📦 Interface Properties
Phần tiê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}🔀 Multiple Interface Inheritance
Phần tiêu đề “🔀 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
Phần tiêu đề “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
Phần tiêu đề “🏛️ Interface vs Abstract Class”| Feature | Interface | Abstract Class |
|---|---|---|
| State (fields) | ❌ Không | ✅ Có |
| Constructor | ❌ Không | ✅ Có |
| Multiple inheritance | ✅ Có | ❌ Không |
| Default implementations | ✅ Có | ✅ Có |
| Visibility modifiers | Chỉ public | Tất cả |
| Dùng khi | Contract, behavior | Shared base + state |
// Interface - chỉ behavior, không có stateinterface Logger { fun log(message: String)}
// Abstract class - shared implementation + stateabstract 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
Phần tiêu đề “🎯 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 consolePrinterclass 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
Phần tiêu đề “🛠️ 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ợpLờ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
Phần tiêu đề “📱 Trong Android”// Repository patterninterface 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 interfacesinterface OnItemClickListener<T> { fun onItemClick(item: T, position: Int) fun onItemLongClick(item: T, position: Int) = false // Default}
// ViewModel interfaceinterface 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
Phần tiêu đề “⚠️ Lưu ý quan trọng”✅ Checklist - Tự kiểm tra
Phần tiêu đề “✅ 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