Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

واجهات متعددة

جزء من قسم البرمجة كائنية التوجه في رحلة Kotlin على Coddy. الدرس 24 من 57.

يمكن للصنف تنفيذ عدة واجهات، تفصل بينها فواصل. ويجب عليه تنفيذ أعضاء جميع هذه الواجهات:

interface Switchable {
    var isOn: Boolean
    fun toggle() { isOn = !isOn }
}
interface Dimmable {
    var level: Int
}
class Lamp : Switchable, Dimmable {
    override var isOn = false
    override var level = 100
}

داخل main:

val lamp = Lamp()
lamp.toggle()
lamp.level = 40
println("${lamp.isOn} ${lamp.level}")

الناتج:

true 40

يمكن للفئة أن ترث من فئة واحدة وتطبّق الواجهات في الرأس نفسه. وحده الصنف الفائق لديه استدعاء مُنشئ:

open class Device(val name: String)
interface Rechargeable {
    fun charge(): String
}
class Phone(name: String) : Device(name), Rechargeable {
    override fun charge() = "$name is charging"
}

داخل main:

println(Phone("Pixel").charge())

الناتج:

Pixel is charging

عندما تمنح واجهتان كلتاهما الطريقة نفسها تطبيقًا افتراضيًا، يجب على الصنف إعادة تعريفها وتحديد ما يجب فعله. تستدعي super<Name>.method() إصدار طريقة من واجهة معينة:

interface Camera {
    fun describe() = "takes photos"
}
interface Telephone {
    fun describe() = "makes calls"
}
class SmartPhone : Camera, Telephone {
    override fun describe() = super<Telephone>.describe() + " and " + super<Camera>.describe()
}

داخل main:

println(SmartPhone().describe())

الناتج:

makes calls and takes photos

يمكن لواجهة أن توسّع واجهات أخرى. يجب على الفئة التي تنفّذ الواجهة المدمجة توفير أعضاء جميع هذه الواجهات، وتُعدّ كل واحدة منها:

interface Named {
    val name: String
}
interface Contact : Named {
    val email: String
    fun card() = "$name <$email>"
}
class Person(override val name: String, override val email: String) : Contact

داخل main:

val ada = Person("Ada", "ada@example.com")
val named: Named = ada
println(ada.card())
println(named.name)

الناتج:

Ada <ada@example.com>
Ada
challenge icon

التحدي

سهل
Switchable ‏isOn (قيمة Boolean للقراءة فقط بالنسبة إلى المستدعين) وtoggle()، بينما تتطلب Dimmable قيمة brightness قابلة للكتابة. اجعل SmartLamp يطبّق كلتا الواجهتين: يبدأ وهو مطفأ وبسطوع 100، وتبدّل toggle() حالته بين التشغيل والإيقاف، وتُقيَّد قيمة السطوع خارج النطاق من 0 إلى 100 بواسطة المُعيِّن، وتُرجع status() القيمة on 70% أو off.

يقرأ الكود المُزوَّد الأوامر toggle أو رقم سطوع، ويطبّقها على مصباح واحد ويطبع status() بعد كل أمر، ثم يتحقق من أن المصباح هو Switchable وDimmable.

ضع كودك في Switchable.kt وDimmable.kt وSmartLamp.kt. يحتوي Main.kt على كود الإدخال/الإخراج المُزوَّد، ولا يمكن تعديله.

جرّب بنفسك

fun main() {
    // كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
    val input = generateSequence(::readLine).toList()
    val lamp = SmartLamp()
    for (cmd in input) {
        if (cmd == "toggle") lamp.toggle() else lamp.brightness = cmd.toInt()
        println(lamp.status())
    }
    println("switchable: ${(lamp as Any) is Switchable}, dimmable: ${(lamp as Any) is Dimmable}")
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: Playground لـ Kotlin