ارثبری و Interface؛ خانوادهسازی بدون دعوای ارث
کدها هم گاهی پدر و فرزند دارن؛ فقط باید اصولی باشه که آخرش دادگاه نره.
کلاسها پیشفرض final هستن
در کاتلین کلاسها بهصورت پیشفرض قابل ارثبری نیستن. برای ارثبری باید `open` بنویسی. این کار جلوی طراحی شلخته رو میگیره؛ هرکی از راه رسید از کلاست بچه نسازه.
مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامهنویسی با نگاه کردن یاد گرفته نمیشود، با خراب کردن و درست کردن جا میافتد.
open class Animal(val name: String) {
open fun sound() = "..."
}
class Cat(name: String) : Animal(name) {
override fun sound() = "Meow"
}
fun main() {
val cat = Cat("پشمک")
println(cat.sound())
}
Meow
Interface یعنی قرارداد
interface میگه هرکلاسی که منو قبول کرد، باید این رفتارها رو داشته باشه. مثل قرارداد کار؛ امضا کردی، دیگه باید انجام بدی.
مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامهنویسی با نگاه کردن یاد گرفته نمیشود، با خراب کردن و درست کردن جا میافتد.
interface Clickable {
fun click()
}
class Button : Clickable {
override fun click() {
println("کلیک شد!")
}
}
خروجی مستقیم ندارد؛ کلاس Button قرارداد Clickable را اجرا کرده و آماده صدا زدن click() است.
Polymorphism
میتونی چند نوع مختلف رو با یک نوع مشترک کنترل کنی. این باعث میشه کد انعطافپذیرتر بشه و با هر تغییر کوچیک، کل پروژه مثل دومینو نریزه.
مثال را با چند مقدار دیگر هم امتحان کن؛ چون برنامهنویسی با نگاه کردن یاد گرفته نمیشود، با خراب کردن و درست کردن جا میافتد.
fun makeItClick(view: Clickable) {
view.click()
}
fun main() {
makeItClick(Button())
}
کلیک شد!
نتیجه این درس 🎯
ارثبری و interface وقتی خوباند که رابطه واقعی وجود داشته باشد. اگر فقط برای کلاسبازی استفادهشان کنی، پروژه بعداً تبدیل به شجرهنامه قاجاری میشود.
تمرین! 🧠
یک interface به نام Payable بساز و کلاس Invoice را مجبور کن تابع pay را پیادهسازی کند.
interface Payable {
fun pay()
}
class Invoice(private val amount: Int) : Payable {
override fun pay() {
println("پرداخت $amount تومان انجام شد")
}
}
fun main() {
val invoice = Invoice(250000)
invoice.pay()
}
پرداخت 250000 تومان انجام شد