فئات البيانات
جزء من قسم البرمجة كائنية التوجه في رحلة Kotlin على Coddy. الدرس 32 من 57.
فئة البيانات هي فئة تتمثل مهمتها الرئيسية في الاحتفاظ بالبيانات. يجعل المُعدِّل data المترجمَ يُنشئ toString() وequals() وhashCode() وcopy() وcomponentN() من خصائص المُنشئ الأساسي:
data class Point(val x: Int, val y: Int)داخل main:
val a = Point(1, 2)
val b = Point(1, 2)
println(a)
println(a == b)
println(setOf(a, b).size)الناتج:
Point(x=1, y=2)
true
1من دون data، يعرض println اسم الفئة ورمز تجزئة مثل Point@1b6d3586، ولا يكون كائنان لهما القيم نفسها متساويين. تنشئ copy() كائنًا جديدًا مع تغيير بعض الخصائص وتترك الكائن الأصلي كما هو، ولذلك تعمل فئة data ذات الخصائص val كقيمة غير قابلة للتغيير:
data class User(val name: String, val email: String, val admin: Boolean = false)داخل main:
val ada = User("Ada", "ada@example.com")
val boss = ada.copy(admin = true)
println(ada)
println(boss)
println(ada == boss)الناتج:
User(name=Ada, email=ada@example.com, admin=false)
User(name=Ada, email=ada@example.com, admin=true)
falseتقوم تصريحات التفكيك بفكّ كائن إلى متغيرات: يستدعي val (x, y) = point الدالتين المُنشأتين component1() وcomponent2()، بترتيب المُنشئ. ويعمل ذلك أيضًا في حلقات for ومعاملات لامبدا، بينما تتخطى _ خاصية:
data class Score(val player: String, val points: Int, val level: Int)داخل main:
val scores = listOf(Score("ada", 120, 3), Score("bo", 95, 2))
for ((player, points) in scores) println("$player: $points")
val (_, bestPoints, bestLevel) = scores.maxBy { it.points }
println("best: $bestPoints at level $bestLevel")الناتج:
ada: 120
bo: 95
best: 120 at level 3تشارك خصائص المُنشئ الأساسي فقط: تُستبعد الخاصية المُعلنة في جسم الفئة من toString وequals وhashCode وcopy. تحتاج فئة البيانات إلى مَعلمة مُنشئ واحدة على الأقل، ويجب أن تكون كل مَعلمة val أو var:
data class Reading(val sensor: String, val value: Int) {
var note = ""
}داخل main:
val r1 = Reading("t1", 20)
val r2 = Reading("t1", 20)
r1.note = "checked"
println(r1)
println(r1 == r2)الناتج:
Reading(sensor=t1, value=20)
trueالتحدي
سهلاجعل Book فئة بيانات بحيث تتم طباعتها ومقارنتها حسب القيمة. ثم أكمل ثلاث دوال: تحوّل parse(line) القيمة Dune;Herbert;1965 إلى كائن Book، وتُرجع newEdition(book, year) نسخةً بالسنة الجديدة مع إضافة (new edition) إلى العنوان، وتُرجع describe(book) القيمة Dune by Herbert, 1965 باستخدام إعلان تفكيك.
يحلّل الكود المتوفر كل سطر إدخال، ويطبع كل كتاب، وعدد التكرارات، والطبعة الجديدة للكتاب الأول (بالسنة 2024)، ووصف كل كتاب مميّز.
يجب أن تضع كودك في Book.kt وBookTools.kt. يحتوي Main.kt على كود الإدخال/الإخراج المتوفر، ولا يمكن تعديله.
جرّب بنفسك
fun main() {
// كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
val input = generateSequence(::readLine).toList()
val books = input.map { parse(it) }
for (b in books) println(b)
println("duplicates: ${books.size - books.distinct().size}")
println(newEdition(books[0], 2024))
for (b in books.distinct()) println(describe(b))
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتالمنشئات الأساسيةكتل init والتحقق من الصحةالمنشئات الثانويةمراجعة - بطاقة المكتبة4الوراثة
الأصناف المفتوحة والأصناف الفرعيةتجاوز الأعضاءsuper والمنشئاتالأصناف المجرّدةمراجعة - دليل الموظفين7الفئات الخاصة
فئات البياناتفئات التعدادالتسلسلات الهرمية المغلقةequals، hashCode، toStringمراجعة - متتبّع الطلباتتدرّب بنفسك: Playground لـ Kotlin