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

فئات التعداد

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

يُصرّح enum class عن نوع ذي مجموعة ثابتة من القيم، وهي الثوابت. كل ثابت هو كائن من التعداد، وله name وordinal، وهو موضعه الذي يبدأ من 0. تسرد entries هذه القيم بالترتيب:

enum class Direction { NORTH, EAST, SOUTH, WEST }

داخل main:

val d = Direction.EAST
println(d)
println(d.ordinal)
println(Direction.entries)

الناتج:

EAST
1
[NORTH, EAST, SOUTH, WEST]

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

enum class Coin(val cents: Int) {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    fun label() = "${name.lowercase()} ($cents c)"
}

داخل main:

println(Coin.DIME.label())
println(Coin.entries.sumOf { it.cents })

الناتج:

dime (10 c)
41

إن استخدام when مع تعداد يسرد كل ثابت لا يحتاج إلى else، ويُبلغ المترجم عن أي ثابت مفقود. تبحث valueOf("SOUTH") عن ثابت بالاسم المطابق تمامًا، وتُطلق استثناءً عند إدخال قيمة غير معروفة، لذلك عادةً ما تتم مطابقة الإدخال باستخدام entries.find:

enum class Direction { NORTH, EAST, SOUTH, WEST }

fun turnRight(d: Direction) = when (d) {
    Direction.NORTH -> Direction.EAST
    Direction.EAST -> Direction.SOUTH
    Direction.SOUTH -> Direction.WEST
    Direction.WEST -> Direction.NORTH
}

fun parse(text: String) = Direction.entries.find { it.name == text.uppercase() }

داخل main:

println(turnRight(Direction.valueOf("SOUTH")))
println(parse("north"))
println(parse("up"))

الناتج:

WEST
NORTH
null

يمكن أن يكون للثابت جسمه الخاص وأن يتجاوز إحدى الطرق فيه. ويؤدي التصريح عن الطريقة abstract في التعداد إلى إلزام كل ثابت بتنفيذها:

enum class Op(val symbol: String) {
    PLUS("+") {
        override fun apply(a: Int, b: Int) = a + b
    },
    TIMES("*") {
        override fun apply(a: Int, b: Int) = a * b
    };

    abstract fun apply(a: Int, b: Int): Int
}

داخل main:

for (op in Op.entries) println("6 ${op.symbol} 3 = ${op.apply(6, 3)}")

الناتج:

6 + 3 = 9
6 * 3 = 18
challenge icon

التحدي

سهل

أكمل التعداد Size بالثوابت SMALL (250 ml، السعر 300)، وMEDIUM (350 ml، 380)، وLARGE (500 ml، 450)، حيث الأسعار بالسنتات. تُرجع label() القيمة medium (350 ml): 3.80، وتُرجع upsize() الحجم الأكبر التالي، أو الحجم نفسه بالنسبة إلى LARGE. تبحث الدالة parse(text) التابعة للكائن المرافق عن حجم مطابق لاسمه مع تجاهل حالة الأحرف، أو بالحرف الأول منه (s، M)، وتُرجع null بخلاف ذلك.

يقرأ الكود المزوَّد طلبات مثل medium أو L أو up small (المشروب ذو الحجم الأكبر) ويطبع كل تسمية أو unknown size x، ثم يطبع في النهاية total: 11.10.

ضع الكود الخاص بك في Size.kt. يحتوي Main.kt على كود الإدخال/الإخراج المزوَّد ولا يمكن تعديله.

جرّب بنفسك

fun main() {
    // كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val upsize = line.startsWith("up ")
        val size = Size.parse(line.removePrefix("up "))
        if (size == null) {
            println("unknown size $line")
            continue
        }
        val chosen = if (upsize) size.upsize() else size
        println(chosen.label())
        total += chosen.price
    }
    println("total: %d.%02d".format(total / 100, total % 100))
}
quiz iconاختبر نفسك

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

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

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