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

دوال التوسعة

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

تضيف دالة الامتداد دالةً إلى نوع موجود من دون تغيير الشيفرة المصدرية للنوع. يُكتب اسمها بعد نوع المُستقبِل، وداخلها تشير this إلى المُستقبِل، ويمكن أيضًا حذفها:

fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0

داخل main:

println("hello".shout())
println(7.isEven())
println(listOf(1, 2, 3, 4).count { it.isEven() })

الناتج:

HELLO!
false
2

تعمل الامتدادات مع أصنافك الخاصة أيضًا، وتضيف خصائص الامتداد خصائص محسوبة. لا يمكن للامتداد إضافة حالة مخزّنة، ولا يصل إلا إلى الأعضاء العامة للمستقبِل:

class Temperature(val celsius: Double)

val Temperature.fahrenheit: Double
    get() = celsius * 9 / 5 + 32

fun Temperature.describe() = "$celsius C is $fahrenheit F"

داخل main:

println(Temperature(100.0).describe())

الناتج:

100.0 C is 212.0 F

يتم تحليل الامتدادات بشكل ثابت: يحدد النوع المُعلَن للتعبير الامتدادَ عند تجميع البرنامج، وليس فئة الكائن. وهذا هو الفرق الرئيسي عن عضو تمت إعادة تعريفه:

open class Shape {
    open fun member() = "shape member"
}
class Circle : Shape() {
    override fun member() = "circle member"
}

fun Shape.ext() = "shape extension"
fun Circle.ext() = "circle extension"

داخل main:

val s: Shape = Circle()
println(s.member())
println(s.ext())

الناتج:

circle member
shape extension

عندما يكون لدى الفئة عضو بالتوقيع نفسه بالفعل، يفوز العضو دائمًا. استخدم الأعضاء للسلوك الذي ينتمي إلى النوع والذي قد تتم إعادة تعريفه؛ واستخدم الامتدادات للمساعدات المُضافة من الخارج، مثل التنسيق لفئة لا تملكها:

class Robot {
    fun greet() = "member greet"
}

fun Robot.greet() = "extension greet"
fun Robot.wave() = "extension wave"

داخل main:

val r = Robot()
println(r.greet())
println(r.wave())

الناتج:

member greet
extension wave
challenge icon

التحدي

سهل

يتم توفير Money(cents) في Money.kt. اكتب الامتدادات الخاصة به في MoneyExtensions.kt: خصائص الامتداد Int.dollars وInt.cents، اللتان تحولان رقمًا إلى Money (حيث إن 12.dollars تساوي 1200 سنت)، وMoney.format()، التي تُرجع $12.50 (أو -$3.05 للمبالغ السالبة)، وList<Money>.total()، التي تُرجع المجموع كقيمة من نوع Money، وMoney.split(parts)، التي تقسّم المبلغ إلى parts من القيم التي يختلف بعضها عن بعض بمقدار سنت واحد على الأكثر، مع وضع القيم الأكبر أولًا.

يقرأ الكود المقدم أسطرًا مثل 12 dollars أو 50 cents، وسطرًا أخيرًا يحتوي على عدد الأجزاء. ويطبع كل مبلغ، ثم total: $12.50 وsplit 3: $4.17 $4.17 $4.16.

يجب وضع كودك في MoneyExtensions.kt وMoney.kt. يحتوي Main.kt على كود الإدخال/الإخراج المقدم، ولا يمكن تعديله.

جرّب بنفسك

fun main() {
    // كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
    val input = generateSequence(::readLine).toList()
    val amounts = input.dropLast(1).map { line ->
        val (n, unit) = line.split(" ")
        if (unit == "dollars") n.toInt().dollars else n.toInt().cents
    }
    for (m in amounts) println(m.format())
    val total = amounts.total()
    println("total: ${total.format()}")
    val parts = input.last().toInt()
    println("split $parts: " + total.split(parts).joinToString(" ") { it.format() })
}
quiz iconاختبر نفسك

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

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

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