فئات التعداد
جزء من قسم البرمجة كائنية التوجه في رحلة 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التحدي
سهلأكمل التعداد 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))
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتالمنشئات الأساسيةكتل init والتحقق من الصحةالمنشئات الثانويةمراجعة - بطاقة المكتبة4الوراثة
الأصناف المفتوحة والأصناف الفرعيةتجاوز الأعضاءsuper والمنشئاتالأصناف المجرّدةمراجعة - دليل الموظفين7الفئات الخاصة
فئات البياناتفئات التعدادالتسلسلات الهرمية المغلقةequals، hashCode، toStringمراجعة - متتبّع الطلباتتدرّب بنفسك: Playground لـ Kotlin