يشكّل هذا الدرس التطبيقي التدريبي جزءًا من الدورة التدريبية لبرمجة مطوّري البرامج في Kolin. ستحصل على أقصى قيمة ممكنة من هذه الدورة التدريبية إذا كنت تستخدم الدروس التطبيقية حول الترميز بشكل متسلسل. بناءً على معلوماتك، قد تتمكّن من تصفّح بعض الأقسام. هذه الدورة التدريبية موجّهة للمبرمجين الذين يعرفون لغة موجّهة نحو الأغراض ويريدون تعلّم لغة Kotlin.
مقدمة
في هذا الدرس التطبيقي حول الترميز، يمكنك إنشاء برنامج Kotlin والتعرّف على الصفوف والكائنات في Kotlin. سيكون معظم هذا المحتوى مألوفًا لك إذا كنت تعرف لغة أخرى موجَّهة إلى الكائن، ولكن لدى لغة Kotlin بعض الاختلافات المهمة لتقليل مقدار الرمز الذي تحتاج إلى كتابته. ستتعلّم أيضًا معلومات عن الصفوف المجرّدة وتفويض الواجهة.
بدلاً من إنشاء نموذج تطبيق واحد، تم تصميم الدروس في هذه الدورة التدريبية لبناء معرفتك، ولكن تكون شبه مستقلة عن بعضها البعض ليتسنى لك تصفح الأقسام التي تعرفها. لربطهما معًا، تستخدم العديد من الأمثلة مظهر معرض أحواض السمك. وإذا أردت الاطّلاع على القصة الكاملة لأحواض السمك، يمكنك الاطّلاع على الدورة التدريبية بعنوان Kotlin Botcamp for Programmers Udacity.
ما يجب معرفته
- أساسيات لغة Kotlin، بما في ذلك الأنواع وعوامل التشغيل وعمليات التكرار
- بنية دالة Kotlin's
- أساسيات البرمجة الموجَّهة للعناصر
- أساسيات IDE مثل IntelliJ IDEA أو Android Studio
ما ستتعرَّف عليه
- كيفية إنشاء دروس والوصول إلى المواقع في Kotlin
- كيفية إنشاء واستخدام أدوات إنشاء الصفوف في Kotlin
- كيفية إنشاء فئة فرعية وآلية اكتسابها
- لمحة عن الصفوف والتجريد والواجهات
- كيفية إنشاء فئات البيانات واستخدامها
- كيفية استخدام الدرجات المفردة، والتعداد، والصفوف المغلقة
الإجراءات التي ستنفذّها
- إنشاء صف دراسي مع خصائص
- إنشاء أداة إنشاء للصف
- إنشاء فئة فرعية
- فحص أمثلة للصفوف المجرّدة والواجهات
- إنشاء فئة بيانات بسيطة
- تعرَّف على درجة العوام، والتعداد، والصفوف المغلقة.
يجب أن تكون مصطلحات البرمجة التالية مألوفة لك:
- الصفوف هي مخططات للعناصر. على سبيل المثال، الفئة
Aquarium
هي مخطط لصنع كائن أكواريوم. - الكائنات هي أمثلة للفئات، كما أن كائن الأكواريوم هو
Aquarium
فعلي واحد. - الخصائص هي خصائص الفئات، مثل طول
Aquarium
وعرضه وارتفاعه. - الطُرق، التي تُعرف أيضًا باسم دوال الأعضاء، هي وظيفة الصف. الطرق هي ما يمكنك قوله مع "الكثير من" على سبيل المثال، يمكنك
fillWithWater()
استخدام الكائنAquarium
. - الواجهة هي مواصفات يمكن للصف تنفيذها. على سبيل المثال، عادة ما يكون التنظيف أمرًا شائعًا بخلاف الأحواض، وغالبًا ما يحدث التنظيف بطرق مماثلة لكائنات مختلفة. لذلك، قد يكون لديك واجهة باسم
Clean
تحدد طريقةclean()
. يستطيع الصفAquarium
تنفيذ الواجهةClean
لتنظيف حوض السمك باستخدام اسفنجة استحمام ناعمة. - الحزم هي طريقة لتجميع الرموز ذات الصلة للحفاظ على تنظيمها أو لإنشاء مكتبة من الرموز. بعد إنشاء حزمة، يمكنك استيراد محتوى الحزمة إلى ملف آخر وإعادة استخدام الرمز والصفوف فيه.
في هذه المهمة، يمكنك إنشاء حزمة جديدة وفئة تحتوي على بعض الخصائص والطريقة.
الخطوة 1: إنشاء حزمة
تساعدك الحِزم في الحفاظ على تنظيم الرمز.
- في جزء المشروع، ضمن مشروع مرحبًا Kotlin، انقر بزر الماوس الأيمن على المجلد src.
- اختَر New > Package (جديد >؛ اسم الحزمة) وامنحها اسم
example.myapp
.
الخطوة 2: إنشاء صف باستخدام الخصائص
يتم تحديد الصفوف بالكلمات الرئيسية class
، في حين تبدأ أسماء الفئات بحرف كبير.
- انقر بزر الماوس الأيمن على الحزمة example.myapp.
- اختَر New > Kotlin File / Class.
- ضِمن النوع، اختَر الصف الدراسي، ثم أدخِل اسمًا للصف
Aquarium
. يتضمن IntelliJ IDEA اسم الحزمة في الملف وينشئ فئةAquarium
فارغة لك. - داخل الفئة
Aquarium
، حدِّد خصائصvar
لإعدادها وارتفاعها وارتفاعها (بالسنتيمتر) وإعدادها. يجب إعداد المواقع بالقيم التلقائية.
package example.myapp
class Aquarium {
var width: Int = 20
var height: Int = 40
var length: Int = 100
}
ضمن الخيارات المتقدمة، تُنشئ لغة Kotlin تلقائيًا أدوات القياس والضبط للخصائص التي حدّدتها في فئة Aquarium
، حتى تتمكن من الوصول إلى المواقع مباشرةً، على سبيل المثال، myAquarium.length
.
الخطوة 3: إنشاء دالة main()
أنشئ ملفًا جديدًا باسم main.kt
للاحتفاظ بوظيفة main()
.
- في لوحة المشروع على يمين الصفحة، انقر بزر الماوس الأيمن على الحزمة example.myapp.
- اختَر New > Kotlin File / Class.
- ضمن القائمة المنسدلة Kind (النوع)، احتفظ بالاختيار ملف، ثم أدخِل اسمًا للملف
main.kt
. يتضمن IntelliJ IDEA اسم الحزمة، ولكنه لا يتضمن تعريف الفئة للملف. - اختَر دالة
buildAquarium()
وفي داخلها إنشاء مثيلAquarium
. لإنشاء مثيل، ارجع إلى الفئة كما لو كانت دالة،Aquarium()
. وهذا يستدعي دالة الصف وينشئ مثالاً للصفAquarium
، على غرار استخدامnew
بلغات أخرى. - اختَر دالة
main()
واستدعِbuildAquarium()
.
package example.myapp
fun buildAquarium() {
val myAquarium = Aquarium()
}
fun main() {
buildAquarium()
}
الخطوة 4: إضافة طريقة
- في صف
Aquarium
، أضِف طريقة لطباعة خصائص حوض الأسماك والأكواريوم.
fun printSize() {
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm ")
}
- في تطبيق
main.kt
، فيbuildAquarium()
، يمكنك الاتصال بالطريقةprintSize()
علىmyAquarium
.
fun buildAquarium() {
val myAquarium = Aquarium()
myAquarium.printSize()
}
- شغِّل برنامجك بالنقر على المثلث الأخضر بجانب دالة
main()
. راقب النتيجة.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm
- في
buildAquarium()
، أضِف الرمز لضبط الارتفاع على 60 واطبع خصائص البُعد التي تم تغييرها.
fun buildAquarium() {
val myAquarium = Aquarium()
myAquarium.printSize()
myAquarium.height = 60
myAquarium.printSize()
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm Width: 20 cm Length: 100 cm Height: 60 cm
في هذه المهمة، يمكنك إنشاء دالة إنشاء للصف ومواصلة العمل باستخدام الخصائص.
الخطوة 1: إنشاء ملف شخصي
في هذه الخطوة، يمكنك إضافة دالة إنشاء إلى صف Aquarium
الذي أنشأته في المهمة الأولى. في المثال السابق، يتم إنشاء كل نسخة افتراضية من Aquarium
باستخدام الأبعاد نفسها. ويمكنك تغيير السمات بعد إنشائها من خلال إعداد الخصائص، ولكن قد يكون من الأسهل إنشاء الحجم الصحيح للبدء بها.
في بعض لغات البرمجة، يتم تعريف التصميم عن طريق إنشاء طريقة داخل الصف تحمل الاسم نفسه للصف الدراسي. في لغة Kotlin، يمكنك تحديد طريقة وضع الملف مباشرةً في تعريف الصف نفسه، مع تحديد المعلمات داخل الأقواس كما لو كانت الفئة طريقة. وكما هو الحال مع الدوال في لغة Kotlin، يمكن أن تتضمن هذه المعلمات قيمًا تلقائية.
- في الصف
Aquarium
الذي أنشأته سابقًا، غيِّر تعريف الفئة لتضمين ثلاث معلّمات داعم مع قيم تلقائية للسمةlength
وwidth
وheight
، وخصِّصها للخصائص المقابلة لها.
class Aquarium(length: Int = 100, width: Int = 20, height: Int = 40) {
// Dimensions in cm
var length: Int = length
var width: Int = width
var height: Int = height
...
}
- وتتميّز لغة Kotlin بأنها أصغر حجمًا من خلال تحديد المواقع التي تتضمّن أدوات الإنشاء مباشرةً، وذلك باستخدام
var
أوval
، كما تعمل لغة Kotlin أيضًا على إنشاء أدوات القياس والضبط. وبعد ذلك، يمكنك إزالة تعريفات الخصائص في نص الصف الدراسي.
class Aquarium(var length: Int = 100, var width: Int = 20, var height: Int = 40) {
...
}
- عند إنشاء كائن
Aquarium
باستخدام طريقة وضع التصميم هذه، لا يمكنك تحديد أي وسيطات والحصول على قيم تلقائية أو تحديد بعض منها فقط، أو تحديد كل منها وإنشاء كائنAquarium
بحجم كامل. في الدالةbuildAquarium()
، جرِّب طرقًا مختلفة لإنشاء كائنAquarium
باستخدام المعلّمات المسماة.
fun buildAquarium() {
val aquarium1 = Aquarium()
aquarium1.printSize()
// default height and length
val aquarium2 = Aquarium(width = 25)
aquarium2.printSize()
// default width
val aquarium3 = Aquarium(height = 35, length = 110)
aquarium3.printSize()
// everything custom
val aquarium4 = Aquarium(width = 25, height = 35, length = 110)
aquarium4.printSize()
}
- شغِّل البرنامج ولاحظ النتائج.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm Width: 25 cm Length: 100 cm Height: 40 cm Width: 20 cm Length: 110 cm Height: 35 cm Width: 25 cm Length: 110 cm Height: 35 cm
تجدر الإشارة إلى أنك لم تضطر إلى زيادة أعباء المُنشئ وصياغة نسخة مختلفة لكل من هذه الحالات (بالإضافة إلى بعض الأعداد الأخرى للنُسخ الأخرى). تنشئ لغة البرمجة Kotlin ما هو مطلوب من القيم التلقائية والمعلّمات المحدّدة.
الخطوة 2: إضافة كائن init
وتنص نماذج الإنشاء أعلاه على الخصائص فقط وتخصص قيمة تعبير لها. إذا كانت العارضة بحاجة إلى رمز إعداد إضافي، يمكن وضعها في قالب init
واحد أو أكثر. في هذه الخطوة، يمكنك إضافة بعض قوالب init
إلى صف واحد (Aquarium
).
- في الفئة
Aquarium
، أضِف كتلةinit
لطباعة العنصر الذي يجري إعداده، وجزء آخر لطباعة الحجم باللتر.
class Aquarium (var length: Int = 100, var width: Int = 20, var height: Int = 40) {
init {
println("aquarium initializing")
}
init {
// 1 liter = 1000 cm^3
println("Volume: ${width * length * height / 1000} l")
}
}
- شغِّل البرنامج ولاحظ النتائج.
aquarium initializing
Volume: 80 l
Width: 20 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 100 l
Width: 25 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 77 l
Width: 20 cm Length: 110 cm Height: 35 cm
aquarium initializing
Volume: 96 l
Width: 25 cm Length: 110 cm Height: 35 cm
تجدر الإشارة إلى أنّه يتم تنفيذ قوالب init
بالترتيب الذي تظهر به في تعريف الفئة، ويتم تنفيذها جميعًا عند استدعاء المنشئ.
الخطوة 3: التعرّف على أدوات الإنشاء الثانوية
وفي هذه الخطوة، يمكنك التعرّف على أدوات الإنشاء الثانوية وإضافة واحدة إلى صفك. بالإضافة إلى طريقة الإنشاء الأساسية التي يمكن أن تحتوي على قالب init
واحد أو أكثر، يمكن أن تتضمن فئة Kotlin أيضًا واحدة أو أكثر من أدوات الإنشاء الثانوية للسماح بإنشاء حِزم وضع المُنشئ طريقة مختلفة، أي الداعمات المختلفة التي لها وسيطات مختلفة.
- في الصف
Aquarium
، أضِف دالة إنشاء ثانوية تستخدم عددًا من الأسماك كوسيطة لها، باستخدام الكلمة الرئيسيةconstructor
. يمكنك إنشاء خاصية خزّانval
بحجم الأحواض المحسوبة باللتر استنادًا إلى عدد الأسماك. لنفترض أن هناك 2 لتر من المياه لكل سمكة، (2000 سم^3)، بالإضافة إلى مساحة إضافية حتى لا يتسرب المياه.
constructor(numberOfFish: Int) : this() {
// 2,000 cm^3 per fish + extra room so water doesn't spill
val tank = numberOfFish * 2000 * 1.1
}
- داخل طريقة الإنشاء الثانوية، احتفِظ بالطول والعرض (الذي تم تحديده في أداة الإنشاء الأساسية) واحسب الارتفاع اللازم لجعل الخزان بمستوى الصوت المحدّد.
// calculate the height needed
height = (tank / (length * width)).toInt()
- في الدالة
buildAquarium()
، يمكنك إضافة استدعاء لإنشاءAquarium
باستخدام دالة الإنشاء الثانوية الجديدة. اطبع الحجم والحجم.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
println("Volume: ${aquarium6.width * aquarium6.length * aquarium6.height / 1000} l")
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ aquarium initializing Volume: 80 l Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 l
يُرجى ملاحظة أن الحجم يُطبَّق مرّتين، مرّة حسب الكتلة init
في المُنشئ الأساسي قبل تنفيذ المُنشئ الثانوي، والثانية من خلال الرمز في buildAquarium()
.
يمكنك تضمين الكلمة الرئيسية constructor
في أداة الإنشاء الأساسية أيضًا، ولكنها ليست ضرورية في معظم الحالات.
الخطوة 4: إضافة أداة إرجاع قيمة جديدة للموقع
في هذه الخطوة، يمكنك إضافة إرجاع قيمة فاضحة للموقع. تحدّد لغة Kotlin تلقائيًا أدوات الاستدعاء والاستدعاءات عند تحديد الخصائص، ولكن في بعض الأحيان يجب تعديل قيمة أحد المواقع أو احتسابها. مثلاً، تمت طباعة حجم Aquarium
أعلاه. يمكنك توفير الحجم كأحد المواقع من خلال تحديد متغيّر وداعٍ له. بما أنّ volume
يجب حسابها، يجب أن تعرِض القيمة الدالة القيمة المحسوبة التي يمكنك تنفيذها باستخدام دالة من سطر واحد.
- في الفئة
Aquarium
، حدِّد خاصيةInt
تُسمىvolume
، وحدِّد طريقةget()
التي تحتسب الحجم في السطر التالي.
val volume: Int
get() = width * height * length / 1000 // 1000 cm^3 = 1 l
- إزالة حظر
init
الذي يطبع مستوى الصوت. - يُرجى إزالة الرمز من خلال
buildAquarium()
الذي يطبع المجلد. - في طريقة
printSize()
، أضِف سطرًا لطباعة الحجم.
fun printSize() {
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm "
)
// 1 l = 1000 cm^3
println("Volume: $volume l")
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ aquarium initializing Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 l
الأبعاد والحجم متطابقان تمامًا كما في السابق، ولكن لا تتم طباعة الحجم إلا مرة واحدة بعد إعداد الكائن بشكل كامل بواسطة كل من طريقة الإنشاء الأساسية وأداة الإنشاء الثانوية.
الخطوة 5: إضافة أداة ضبط للمواقع
في هذه الخطوة، يمكنك إنشاء أداة ضبط مواقع جديدة للحجم.
- في الصف
Aquarium
، عليك تغيير السمةvolume
إلى سمةvar
حتى يتم ضبطها أكثر من مرة. - أضِف مقياسًا لسمتَي
volume
عن طريق إضافة طريقةset()
أسفل وحدة التلقيم، والتي تعيد حساب الارتفاع بناءً على كمية المياه التي يتم توفيرها. وفقًا للاصطلاح، يكون اسم المعلّمة setter هوvalue
، ولكن يمكنك تغييره إذا كنت تفضّل ذلك.
var volume: Int
get() = width * height * length / 1000
set(value) {
height = (value * 1000) / (width * length)
}
- في
buildAquarium()
، أضِف الرمز لضبط مستوى صوت الأكواريوم على 70 لترًا. اطبع الحجم الجديد.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
aquarium6.volume = 70
aquarium6.printSize()
}
- شغِّل البرنامج مرة أخرى ولاحظ الارتفاع والارتفاع اللذين تم تغييرهما.
⇒ aquarium initialized
Width: 20 cm Length: 100 cm Height: 31 cm
Volume: 62 l
Width: 20 cm Length: 100 cm Height: 35 cm
Volume: 70 l
لم تتوفّر أي تعديلات حتى الآن، مثل public
أو private
، في الرمز. هذا، ويعود السبب في ذلك إلى أن كل شيء في لغة Kotlin يكون تلقائيًا بشكل تلقائي، أي أنه يمكن الوصول إلى كل شيء من أي مكان، بما في ذلك الصفوف والطرق والخصائص ومتغيرات الأعضاء.
في لغة Kotlin، يمكن أن تحتوي الفئات والكائنات والواجهات ودوال البناء والدوال والمواقع والخصائص وضبطها على معدّلات ظهور:
- وتعني القيمة
public
خارج الصف. ويكون كل محتوى متاحًا للجميع تلقائيًا، بما في ذلك المتغيّرات وطرق الصف. - وتعني القيمة
internal
أنها ستكون مرئية داخل هذه الوحدة فقط. الوحدة هي مجموعة من ملفات Kotlin التي يتم تجميعها معًا، مثل مكتبة أو تطبيق. - ويعني
private
أنّ الملف سيكون مرئيًا فقط في تلك الفئة (أو ملف المصدر إذا كنت تعمل مع الدوال). protected
هو نفسهprivate
، لكنه سيكون مرئيًا أيضًا لأي فئات فرعية.
اطّلع على مفاتيح تعديل مستوى الرؤية في وثائق Kotlin لمزيد من المعلومات.
متغيرات العضو
وتكون الخصائص داخل الفئة أو المتغيّرات الأعضاء public
تلقائيًا. إذا حدّدتها باستخدام var
، ستكون قابلة للتغيير، أي قابلة للقراءة والكتابة. وإذا حدّدتها باستخدام val
، ستكون للقراءة فقط بعد الإعداد.
إذا كنت تريد موقعًا يمكن للرمز قراءته أو كتابته، ولكن يمكن للرمز الخارجي قراءته فقط، يمكنك ترك الموقع والمُعرّف له على "علني" والتصريح عن "setter" (خاص) كما هو موضح أدناه.
var volume: Int
get() = width * height * length / 1000
private set(value) {
height = (value * 1000) / (width * length)
}
في هذه المهمة، ستتعرّف على آلية عمل الفئات الفرعية والتوريث في لغة Kotlin. وهي تشبه ما رأيته بلغات أخرى، ولكن هناك بعض الاختلافات.
وبشكل تلقائي، لا يمكن تقسيم الصفوف إلى فئات فرعية بلغة Kotlin تلقائيًا. وبالمثل، لا يمكن تجاوز الخصائص ومتغيرات الأعضاء من خلال الفئات الفرعية (على الرغم من إمكانية الوصول إليها).
يجب وضع علامة على صف باعتباره open
للسماح بتصنيفه إلى فئات فرعية. وبالمثل، يجب وضع علامة على الخصائص ومتغيرات الأعضاء على أنها open
، لإلغاء هذه القيم في الفئة الفرعية. الكلمة الرئيسية open
مطلوبة لمنع تسرب تفاصيل التنفيذ عن طريق الخطأ كجزء من واجهة الصف.
الخطوة 1: فتح درس الأكواريوم
في هذه الخطوة، يمكنك إنشاء صف Aquarium
open
، حتى يمكنك تجاوزه في الخطوة التالية.
- ضَع علامة على الفئة
Aquarium
وجميع مواقعها باستخدام الكلمة الرئيسيةopen
.
open class Aquarium (open var length: Int = 100, open var width: Int = 20, open var height: Int = 40) {
open var volume: Int
get() = width * height * length / 1000
set(value) {
height = (value * 1000) / (width * length)
}
- أضف خاصية
shape
مفتوحة بالقيمة"rectangle"
.
open val shape = "rectangle"
- أضِف خاصية
water
المفتوحة التي تحتوي على دَربة تعرض 90% من حجمAquarium
.
open var water: Double = 0.0
get() = volume * 0.9
- يمكنك إضافة رمز إلى طريقة
printSize()
لطباعة الشكل ومقدار الماء كنسبة مئوية من الحجم.
fun printSize() {
println(shape)
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm ")
// 1 l = 1000 cm^3
println("Volume: $volume l Water: $water l (${water/volume*100.0}% full)")
}
- في
buildAquarium()
، غيِّر الرمز لإنشاءAquarium
باستخدامwidth = 25
وlength = 25
وheight = 40
.
fun buildAquarium() {
val aquarium6 = Aquarium(length = 25, width = 25, height = 40)
aquarium6.printSize()
}
- شغِّل برنامجك ولاحظ النتيجة الجديدة.
⇒ aquarium initializing rectangle Width: 25 cm Length: 25 cm Height: 40 cm Volume: 25 l Water: 22.5 l (90.0% full)
الخطوة 2: إنشاء فئة فرعية
- يمكنك إنشاء فئة فرعية من
Aquarium
تُسمىTowerTank
، والتي تستخدم خزانًا أسطوانيًا مستديرًا بدلاً من خزان مستطيل. يمكنك إضافةTowerTank
أقل منAquarium
، لأنه يمكنك إضافة صف آخر في الملف نفسه كصفAquarium
. - في
TowerTank
، يمكنك إلغاء الخاصيةheight
التي يتم تعريفها في دالة الإنشاء. لإلغاء موقع إلكتروني، استخدِم الكلمة الرئيسيةoverride
في الفئة الفرعية.
- جعل أداة إنشاء
TowerTank
تتخذdiameter
. استخدِمdiameter
لكل منlength
وwidth
عند استدعاء دالة الإنشاء في الفئة العليا علىAquarium
.
class TowerTank (override var height: Int, var diameter: Int): Aquarium(height = height, width = diameter, length = diameter) {
- تجاوز خاصية الحجم لحساب أسطوانة. صيغة الأسطوانة هي باي مضروبًا في نصف قطر القسمة في الارتفاع. يجب استيراد قيمة
PI
الثابتة منjava.lang.Math
.
override var volume: Int
// ellipse area = π * r1 * r2
get() = (width/2 * length/2 * height / 1000 * PI).toInt()
set(value) {
height = ((value * 1000 / PI) / (width/2 * length/2)).toInt()
}
- في
TowerTank
، عليك إلغاء خاصيةwater
لتكون 80% من مستوى الصوت.
override var water = volume * 0.8
- إلغاء
shape
لتصبح"cylinder"
.
override val shape = "cylinder"
- من المفترض أن يبدو الصف الأخير من
TowerTank
مثل الرمز أدناه.
Aquarium.kt
:
package example.myapp
import java.lang.Math.PI
... // existing Aquarium class
class TowerTank (override var height: Int, var diameter: Int): Aquarium(height = height, width = diameter, length = diameter) {
override var volume: Int
// ellipse area = π * r1 * r2
get() = (width/2 * length/2 * height / 1000 * PI).toInt()
set(value) {
height = ((value * 1000 / PI) / (width/2 * length/2)).toInt()
}
override var water = volume * 0.8
override val shape = "cylinder"
}
- في
buildAquarium()
، أنشئTowerTank
بقطر 25 سم وارتفاع 45 سم. اطبع الحجم.
main.kt:
package example.myapp
fun buildAquarium() {
val myAquarium = Aquarium(width = 25, length = 25, height = 40)
myAquarium.printSize()
val myTower = TowerTank(diameter = 25, height = 40)
myTower.printSize()
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ aquarium initializing rectangle Width: 25 cm Length: 25 cm Height: 40 cm Volume: 25 l Water: 22.5 l (90.0% full) aquarium initializing cylinder Width: 25 cm Length: 25 cm Height: 40 cm Volume: 18 l Water: 14.4 l (80.0% full)
في بعض الأحيان، قد ترغب في تحديد سلوكيات أو خصائص مشتركة ستتم مشاركتها بين بعض الصفوف ذات الصلة. يقدم Kotlin طريقتين لإجراء ذلك، الواجهات والصفوف تجريدية. في هذه المَهمّة، يمكنك إنشاء فئة مجرّدة من AquariumFish
للخصائص المشتركة بين جميع الأسماك. يمكنك إنشاء واجهة باسم FishAction
لتحديد السلوك المشترك مع جميع الأسماك.
- لا يمكن إنشاء مثيل لفئة مجردة أو واجهة بشكل مستقل، مما يعني أنه لا يمكنك إنشاء عناصر من هذه الأنواع مباشرةً.
- تحتوي الصفوف التجريدية على أدوات إنشاء.
- لا يمكن أن تحتوي الواجهات على أي منطق إنشاء أو تخزّن أي حالة.
الخطوة الأولى: إنشاء صف تجريدي
- ضمن example.myapp، أنشئ ملفًا جديدًا،
AquariumFish.kt
. - إنشاء صف دراسي، يُسمّى أيضًا باسم
AquariumFish
، ووضع علامة عليه باستخدامabstract
. - أضِف خاصية
String
واحدة (color
)، وضَع علامة عليها باستخدامabstract
.
package example.myapp
abstract class AquariumFish {
abstract val color: String
}
- أنشئ فئتين فرعيتين من
AquariumFish
وShark
وPlecostomus
. - نظرًا لأن
color
مجرّد، على الفئات الفرعية تنفيذه. ضبطShark
على اللون الرمادي وPlecostomus
من الذهب
class Shark: AquariumFish() {
override val color = "gray"
}
class Plecostomus: AquariumFish() {
override val color = "gold"
}
- في main.kt، أنشِئ دالة
makeFish()
لاختبار صفوفك. أنشئ مثيلًا للسمةShark
وPlecostomus
، ثم اطبع لون كل منها. - يمكنك حذف الرمز التجريبي السابق في
main()
وإضافة مكالمة إلىmakeFish()
. ويجب أن يظهر الرمز كما يلي.
main.kt
:
package example.myapp
fun makeFish() {
val shark = Shark()
val pleco = Plecostomus()
println("Shark: ${shark.color}")
println("Plecostomus: ${pleco.color}")
}
fun main () {
makeFish()
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ Shark: gray Plecostomus: gold
يمثل المخطّط التالي الصفّة Shark
والصف Plecostomus
، الذي يُصنّف الفئة الفرعية المجرّدة AquariumFish
.
الخطوة الثانية: إنشاء واجهة
- في Aquaiumfish.kt، أنشئ واجهة باسم
FishAction
باستخدامeat()
.
interface FishAction {
fun eat()
}
- أضف
FishAction
إلى كل فئة من الفئات الفرعية، ونفِّذeat()
من خلال طباعتها في عمل الأسماك.
class Shark: AquariumFish(), FishAction {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
class Plecostomus: AquariumFish(), FishAction {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
- في الدالة
makeFish()
، اطلُب من كل سمكة أنشأتها أن تنشد طعامًا عن طريق استدعاءeat()
.
fun makeFish() {
val shark = Shark()
val pleco = Plecostomus()
println("Shark: ${shark.color}")
shark.eat()
println("Plecostomus: ${pleco.color}")
pleco.eat()
}
- شغِّل برنامجك ولاحظ النتائج.
⇒ Shark: gray hunt and eat fish Plecostomus: gold eat algae
يمثل الرسم البياني التالي كل من الفئة Shark
والصف Plecostomus
، وكلاهما تتألف من واجهة FishAction
وتنفذها.
حالات استخدام الصفوف التجريدية مقابل الواجهات
الأمثلة الموضحة أعلاه بسيطة، ولكن عندما يكون لديك عدد كبير من الصفوف المترابطة، يمكن أن تساعدك الصفوف التجريدية والواجهات على الحفاظ على نظافة تصميمك وأكثر تنظيمًا وأسهل في الصيانة.
كما هو موضّح أعلاه، يمكن أن تتضمّن الصفوف المجرّدة طرق وضع، ولا يمكن إنشاء الواجهات، ولكنها متشابهة جدًا بخلاف ذلك. متى يجب استخدامها؟
عند استخدام واجهات لإنشاء صف، يتم توسيع وظائف الصف الدراسي من خلال مثيلات الصفوف التي تحتوي عليها. غالبًا ما تسهّل المقطوعة الموسيقية عملية إعادة استخدام الرموز والسبب وراء اكتسابها من فئة مجردة. ويمكنك أيضًا استخدام واجهات متعددة في صف دراسي، ولكن لا يمكنك استخدام سوى فئة فرعية من صف تجريدي واحد.
وكثيرًا ما تؤدي التركيبة إلى تحسين التغليف والاقتران الأقل (الاعتمادية) والواجهات الأكثر وضوحًا وقابلية استخدام أكبر للرمز. لهذه الأسباب، يكون استخدام التركيبة مع الواجهات هو التصميم المفضّل. من ناحية أخرى، غالبًا ما يكون التوارث من فئة مجردة مناسبًا لبعض المشاكل. ولهذا السبب، ننصحك بتفضيل التعرّف على المقطوعة الموسيقية، ولكن عندما يكون السبب مفهومًا كبيرًا في لغة البرمجة Kotlin، يمكنك استخدامها أيضًا.
- استخدم واجهة إذا كان لديك الكثير من الطرق وعملية تنفيذ واحدة أو عمليتين تلقائيتين، على سبيل المثال كما في
AquariumAction
أدناه.
interface AquariumAction {
fun eat()
fun jump()
fun clean()
fun catchFish()
fun swim() {
println("swim")
}
}
- استخدم صفًا تجريديًا في أي وقت لا يمكنك فيه إكمال صف دراسي. على سبيل المثال، بالرجوع إلى الصف
AquariumFish
، يمكنك تطبيقAquariumFish
علىFishAction
، وتقديم تنفيذ تلقائي للسمةeat
مع ترك تجريدcolor
، بسبب عدم توفّر لون تلقائي للسمك.
interface FishAction {
fun eat()
}
abstract class AquariumFish: FishAction {
abstract val color: String
override fun eat() = println("yum")
}
تضمّنت المهمة السابقة صفوفًا مجرّدة وواجهات وأفكارًا تتعلّق بالمقطوعة الموسيقية. تفويض الواجهة هو أسلوب متقدم يتم فيه تنفيذ طرق الواجهة من خلال كائن مساعد (أو مفوّض)، والذي تستخدمه الصفّة بعد ذلك. يمكن أن يكون هذا الأسلوب مفيدًا عند استخدام واجهة في سلسلة من الصفوف غير ذات الصلة: تضيف وظيفة الواجهة المطلوبة إلى فئة مساعد منفصلة، وتستخدم كل صفة مثالاً للصف المساعد لتنفيذ الوظيفة.
في هذه المَهمّة، يمكنك استخدام تفويض الواجهة لإضافة وظائف إلى صف.
الخطوة الأولى: إنشاء واجهة جديدة
- في Aquaiumfish.kt، أزِل الفئة
AquariumFish
. بدلاً من التوارث من الفئةAquariumFish
، سيطبّقPlecostomus
وShark
واجهات لكلٍّ من إجراء السمك ولونه. - أنشئ واجهة جديدة،
FishColor
، تحدد اللون كسلسلة.
interface FishColor {
val color: String
}
- يمكنك تغيير
Plecostomus
لتنفيذ واجهتَين،FishAction
وFishColor
. يجب إلغاءcolor
منFishColor
وeat()
منFishAction
.
class Plecostomus: FishAction, FishColor {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
- غيّر فئة
Shark
أيضًا لتنفيذ الواجهتين،FishAction
وFishColor
، بدلاً من اكتسابها منAquariumFish
.
class Shark: FishAction, FishColor {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
- ويجب أن يظهر الرمز النهائي على النحو التالي:
package example.myapp
interface FishAction {
fun eat()
}
interface FishColor {
val color: String
}
class Plecostomus: FishAction, FishColor {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
class Shark: FishAction, FishColor {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
الخطوة 2: إنشاء صف فردي
بعد ذلك، يمكنك تنفيذ إعداد جزء التفويض عن طريق إنشاء صف مساعد يطبِّق FishColor
. يمكنك إنشاء صف أساسي باسم GoldColor
ينفّذ FishColor
، وكل ما يعنيه أن لونه هو الذهب.
ليس من المنطقي إنشاء مثيلات متعددة من GoldColor
، لأنّها جميعًا تنفِّذ الإجراء نفسه. وبالتالي، تتيح لك لغة Kotlin الإعلان عن صف دراسي يمكنك إنشاء مثيل واحد منه باستخدام الكلمة الرئيسية object
بدلاً من class
. سينشئ Kotlin هذا المثيل، ويُشار إليه على اسم الفئة. بعد ذلك، يمكن لجميع الكائنات الأخرى استخدام هذه النسخة الافتراضية فقط - ليس هناك طريقة لإنشاء مثيلات أخرى من هذه الفئة. وإذا كنت معتادًا على نمط فردي، هذه هي الطريقة التي تطبّق بها درجات اللون الفردي في Kotlin.
- في Aquaiumfish.kt، أنشئ كائنًا لـ
GoldColor
. يمكنك إلغاء اللون.
object GoldColor : FishColor {
override val color = "gold"
}
الخطوة 3: إضافة تفويض للواجهة من أجل أسماك اللون
أنت الآن على استعداد لاستخدام تفويض الواجهة.
- في Aquaiumfish.kt، أزِل إلغاء
color
منPlecostomus
. - غيِّر الفئة
Plecostomus
للحصول على لونها منGoldColor
. ويمكنك إجراء ذلك من خلال إضافةby GoldColor
إلى بيان الصف الدراسي وإنشاء التفويض. بناءً على ذلك، بدلاً من تنفيذFishColor
، استخدِم عملية التنفيذ المقدّمة منGoldColor
. وبالتالي في كل مرة يتم فيها الوصول إلىcolor
، يتم تفويضها إلىGoldColor
.
class Plecostomus: FishAction, FishColor by GoldColor {
override fun eat() {
println("eat algae")
}
}
وكما هو الحال مع هذه الصفوف، ستكون جميع نباتات Plecos ذهبية اللون، ولكن هذه السمكة متوفّرة بالفعل بألوان متعددة. يمكنك معالجة هذه المشكلة من خلال إضافة معلمة إنشاء للون مع GoldColor
باعتباره اللون التلقائي لـ Plecostomus
.
- يمكنك تغيير الفئة
Plecostomus
لاجتياز الفئة فيfishColor
باستخدام دالة الإنشاء، وضبط الإعداد التلقائي علىGoldColor
. تغيير التفويض منby GoldColor
إلىby fishColor
.
class Plecostomus(fishColor: FishColor = GoldColor): FishAction,
FishColor by fishColor {
override fun eat() {
println("eat algae")
}
}
الخطوة 4: إضافة تفويض بواجهة تطبيق fishAction
يمكنك أيضًا استخدام تفويض واجهة المستخدم FishAction
.
- في Aquaiumfish.kt أنشئ صف
PrintingFishAction
ينفّذFishAction
، الذي يستغرقString
، ثمfood
، ثم يطبع السمكة.
class PrintingFishAction(val food: String) : FishAction {
override fun eat() {
println(food)
}
}
- في الفئة
Plecostomus
، عليك إزالة وظيفة الإلغاءeat()
، لأنه سيتم استبدالها بتفويض. - في بيان
Plecostomus
، يمكنك تفويضFishAction
إلىPrintingFishAction
، وتجاوز"eat algae"
. - مع كل هذا التفويض، ليس هناك رمز في نص فئة
Plecostomus
، لذا عليك إزالة{}
، لأنه يتم التعامل مع جميع عمليات الإلغاء من خلال تفويض الواجهة
class Plecostomus (fishColor: FishColor = GoldColor):
FishAction by PrintingFishAction("eat algae"),
FishColor by fishColor
يوضّح المخطّط التالي فئتَي Shark
وPlecostomus
، واللتان تتألفان من واجهتي PrintingFishAction
وFishColor
، ولكنهما تفوّضان التنفيذ.
يُعد تفويض الواجهة فعّالاً، ويجب بشكل عام التفكير في كيفية استخدامه كلما أمكنك استخدام صف مجرّد بلغة أخرى. وهو يتيح لك استخدام التركيبة لإضافة السلوكيات، بدلاً من اشتراط العديد من الفئات الفرعية، التي يتخصص كل منها بطريقة مختلفة.
تتشابه فئة البيانات مع struct
في بعض اللغات الأخرى، حيث تتوفّر في الأساس للاحتفاظ ببعض البيانات، ولكن لا يزال عنصر فئة البيانات عبارة عن عنصر. تتمتع عناصر فئة بيانات Kotlin ببعض المزايا الإضافية، مثل المرافق للطباعة والنسخ. في هذه المهمة، يمكنك إنشاء فئة بيانات بسيطة والتعرّف على الدعم الذي يوفّره Kotlin لصفوف البيانات.
الخطوة 1: إنشاء صف بيانات
- أضِف حزمة
decor
جديدة ضمن حزمة example.myapp للاحتفاظ بالرمز الجديد. انقر بزر الماوس الأيمن على example.myapp في جزء المشروع واختَر File > New > Package. - في الحزمة، أنشِئ صفًا جديدًا باسم
Decoration
.
package example.myapp.decor
class Decoration {
}
- لجعل
Decoration
فئة بيانات، ابدأ بيان الصف بالكلمة الرئيسيةdata
. - يجب إضافة السمة
String
التي تحمل الاسمrocks
لتوفير بعض البيانات للصف.
data class Decoration(val rocks: String) {
}
- في الملف خارج الصف، أضِف دالة
makeDecorations()
لإنشاء مثيلDecoration
من خلال"granite"
وطباعته.
fun makeDecorations() {
val decoration1 = Decoration("granite")
println(decoration1)
}
- أضِف دالة
main()
لاستدعاءmakeDecorations()
ونفِّذ برنامجك. لاحظ الإخراج المعقول الذي تم إنشاؤه لأنه عبارة عن فئة بيانات.
⇒ Decoration(rocks=granite)
- في
makeDecorations()
، عليك إنشاء مثيلين لكائنDecoration
آخرَين من نوع واحد، وهما: "& Slate:"
fun makeDecorations() {
val decoration1 = Decoration("granite")
println(decoration1)
val decoration2 = Decoration("slate")
println(decoration2)
val decoration3 = Decoration("slate")
println(decoration3)
}
- في
makeDecorations()
، أضِف بيانًا مطبوعًا يطبع نتيجة مقارنةdecoration1
بـdecoration2
، وثانيًا يقارنdecoration3
معdecoration2
. استخدِم الإجراء equals() الذي تقدّمه فئات البيانات.
println (decoration1.equals(decoration2))
println (decoration3.equals(decoration2))
- شغِّل الرمز.
⇒ Decoration(rocks=granite) Decoration(rocks=slate) Decoration(rocks=slate) false true
الخطوة الثانية: استخدام المحور
للوصول إلى خصائص عنصر بيانات وإسنادها إلى المتغيرات، يمكنك تخصيص واحد تلو الآخر، مثل هذا.
val rock = decoration.rock
val wood = decoration.wood
val diver = decoration.diver
بدلاً من ذلك، يمكنك إنشاء متغيّرات واحدة لكل موقع، وتحديد كائن البيانات لمجموعة المتغيّرات. يضع Kotlin قيمة السمة في كل متغير.
val (rock, wood, diver) = decoration
ويُعرف هذا الإجراء باسم التدمير وهو اختصار مختصر مفيد. يجب أن يتطابق عدد المتغيرات مع عدد الخصائص، ويتم تخصيص المتغيرات بالترتيب الذي تم تعريفها به في الفئة. إليك مثال كامل يمكنك استخدامه في Decoration.kt.
// Here is a data class with 3 properties.
data class Decoration2(val rocks: String, val wood: String, val diver: String){
}
fun makeDecorations() {
val d5 = Decoration2("crystal", "wood", "diver")
println(d5)
// Assign all properties to variables.
val (rock, wood, diver) = d5
println(rock)
println(wood)
println(diver)
}
⇒ Decoration2(rocks=crystal, wood=wood, diver=diver) crystal wood diver
إذا كنت لا تحتاج إلى خاصية واحدة أو أكثر من المواقع، يمكنك تخطيها باستخدام _
بدلاً من اسم المتغير، كما هو موضّح في الرمز أدناه.
val (rock, _, diver) = d5
في هذه المهمة، ستتعرّف على بعض دروس الغرض الخاص في لغة Kotlin، بما في ذلك ما يلي:
- دروس فردية
- عمليات التعداد
- دروس مغلقة
الخطوة 1: استرجاع صفوف مفردة
تذكّر المثال السابق باستخدام الصف GoldColor
.
object GoldColor : FishColor {
override val color = "gold"
}
ونظرًا لأن كل مثيل من GoldColor
ينفذ الإجراء نفسه، يتم تعريفه على أنه object
بدلاً من class
للإشارة إلى فردي. لا يمكن أن يتضمّن الملف أكثر من نسخة واحدة.
الخطوة 2: إنشاء تعداد
ويتيح أيضًا لغة Kotlin التعداد الذي يتيح لك تعدّد الأشياء والإشارة إليها بالاسم، كما هو الحال في اللغات الأخرى. يمكنك الإعلان عن تعداد عن طريق إضافة بادئة إلى الكلمة الرئيسية enum
. يحتاج تعريف التعداد الأساسي إلى قائمة أسماء فقط، ولكن يمكنك أيضًا تحديد حقل واحد أو أكثر مرتبط بكل اسم.
- في Decoration.kt، جرّب مثالًا تعدادًا.
enum class Color(val rgb: Int) {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
}
تعدّ التعداد إلى حد ما درجة أفرد، حيث يمكن أن تكون هناك قيمة واحدة فقط، وقيمة واحدة فقط من كل قيمة في التعداد. على سبيل المثال، لا يمكن أن تكون هناك أكثر من Color.RED
وColor.GREEN
وColor.BLUE
واحد. في هذا المثال، يتم تحديد قيم نموذج أحمر أخضر أزرق (RGB) للسمة rgb
لتمثيل مكوّنات الألوان. يمكنك أيضًا الحصول على القيمة العددية لمجموعة تعداد باستخدام السمة ordinal
واسمها باستخدام السمة name
.
- جرِّب مثالاً آخر للإحصاء.
enum class Direction(val degrees: Int) {
NORTH(0), SOUTH(180), EAST(90), WEST(270)
}
fun main() {
println(Direction.EAST.name)
println(Direction.EAST.ordinal)
println(Direction.EAST.degrees)
}
⇒ EAST 2 90
الخطوة 3: إنشاء صف مغلق
الصف المُغلق هو فئة يمكن تقسيمها فرعيًا، ولكن داخل الملف الذي تم الإعلان عنه فقط. إذا حاولت إنشاء فئة فرعية في ملف مختلف، ستظهر لك رسالة خطأ.
وبما أنّ الفئات والفئات الفرعية في الملف نفسه، سيتعرّف لغة Kotlin على جميع الفئات الفرعية بشكل ثابت. بمعنى أنه في وقت التجميع، يرى المُجمِّع كل الصفوف والصفوف الفرعية ويدرك أن هذا هو جميعها، وبذلك يمكن للمترجم إجراء عمليات فحص إضافية لك.
- في Aquaiumfish.kt، يمكنك تجربة مثال لفئة مغلقة في الحفاظ على المظهر المائي.
sealed class Seal
class SeaLion : Seal()
class Walrus : Seal()
fun matchSeal(seal: Seal): String {
return when(seal) {
is Walrus -> "walrus"
is SeaLion -> "sea lion"
}
}
لا يمكن إجراء تقسيم فرعي للصف Seal
في ملف آخر. إذا أردت إضافة المزيد من أنواع Seal
، عليك إضافتها في الملف نفسه. وهذا يجعل الصفوف المغلقة طريقة آمنة لتمثيل عدد ثابت من الأنواع. على سبيل المثال، تُعدّ الصفوف المغلقة رائعة لتحقيق النجاح أو خطأ من واجهة برمجة تطبيقات الشبكة.
تناول هذا الدرس جوانب كثيرة من الموضوع. وفي حين أن جزءًا كبيرًا من لغة البرمجة Kotlin يجب أن يكون مألوفًا من لغات البرمجة الأخرى التي تركّز على الكائنات، فإن لغة Kotlin تضيف بعض الميزات للحفاظ على شفرة موجزة وسهلة القراءة.
الصفوف ودوال البناء
- يمكنك تحديد صف باللغة Kotlin باستخدام
class
. - تنشئ لغة Kotlin تلقائيًا أدوات الضبط والدعامات للخصائص.
- حدِّد المنشئ الأساسي في تعريف الفئة مباشرةً. على سبيل المثال:
class Aquarium(var length: Int = 100, var width: Int = 20, var height: Int = 40)
- إذا كانت دالة الإنشاء الأساسية بحاجة إلى رمز إضافي، يمكنك كتابتها في مجموعة
init
أو أكثر. - يمكن أن تُحدِّد الفئة طريقة تصميم ثانوية أو أكثر باستخدام
constructor
، ولكن نمط Kotlin هو استخدام دالة المصنع بدلاً من ذلك.
معدِّلات مستوى الرؤية والفئات الفرعية
- كل الصفوف والوظائف في لغة Kotlin هي
public
تلقائيًا، ولكن يمكنك استخدام المعدِّلات لتغيير مستوى الرؤية إلىinternal
أوprivate
أوprotected
. - لإنشاء فئة فرعية، يجب وضع علامة على الفئة الرئيسية
open
. - لإلغاء الطرق والخصائص في فئة فرعية، يجب وضع علامة على الطرق والخصائص
open
في الفئة الرئيسية. - ولا يمكن تصنيف الفئة المغلقة إلا في الملف نفسه الذي يتم تحديدها فيه. أدخِل صفًا مختومًا عن طريق وضع البادئة
sealed
في البيان.
فئات البيانات وعدد الحالات الفردية والتعداد
- أنشِئ فئة بيانات من خلال إضافة بادئة إلى التعريف
data
. - التدمير هو اختصاص لتخصيص خصائص كائن
data
لفصل المتغيرات. - أنشِئ صفًا فرديًا باستخدام
object
بدلاً منclass
. - تحديد تعداد باستخدام
enum class
الصفوف التجريدية والواجهات والتفويض
- تُعد الصفوف والواجهات التجريدية طريقتين لمشاركة السلوك المشترك بين الصفوف.
- تحدد الفئة المجرّدة الخصائص والسلوك، ولكنها تترك عملية التنفيذ للفئات الفرعية.
- تحدِّد الواجهة السلوك، وقد توفّر عمليات تنفيذ تلقائية لبعض السلوكيات أو جميعها.
- عند استخدام واجهات لإنشاء صف، يتم توسيع وظائف الصف الدراسي من خلال مثيلات الصفوف التي تحتوي عليها.
- يستخدم تفويض الواجهة تركيبًا، ولكن أيضًا يفوّض التنفيذ إلى صفوف الواجهة.
- تشكّل المقطوعة الموسيقية طريقة فعالة لإضافة وظائف إلى الصف باستخدام تفويض الواجهة. من المفضّل عادةً استخدام التركيبة العامة، ولكن قد يكون التوارث من فئة مجرّدة أكثر ملاءمةً لبعض المشاكل.
مستندات Kotlin
إذا كنت بحاجة إلى مزيد من المعلومات عن أي موضوع في هذه الدورة التدريبية، أو إذا واجهتك مشكلة، يمكنك البدء باستخدام https://kotlinlang.org.
- الفئات وتوريث المعلومات
- الشركات المصنّعة
- الوظائف المصنع
- الخصائص والحقول
- معدِّلات مستوى الرؤية
- الصفوف التجريدية
- الواجهات
- التفويض
- فئات البيانات
- المساواة
- المحو
- بيانات العنصر
- الصفوف الدراسية
- الصفوف المغلقة
- التعامل مع الأخطاء الاختيارية باستخدام صفوف Kotlin مغلقة
برامج تعليمية بلغة Kotlin
يتضمّن الموقع الإلكتروني https://try.kotlinlang.org برامج تعليمية غنية اسمها Kotlin Koans ومترجمًا فوريًا مستندًا إلى الويب ومجموعة كاملة من المستندات المرجعية التي تتضمّن أمثلة.
دورة Udacity التدريبية
للاطّلاع على دورة Udacity التدريبية حول هذا الموضوع، يُرجى الاطّلاع على برنامج Kotlin Campus للمبرمجين.
IntelliJ IDEA
يمكن العثور على مستندات IntelliJ IDEA على الموقع الإلكتروني JetBrains.
يسرد هذا القسم المهام الدراسية المحتملة للطلاب الذين يعملون من خلال هذا الدرس التطبيقي حول الترميز في إطار دورة تدريبية يُديرها معلِّم. يجب أن ينفِّذ المعلّم ما يلي:
- يمكنك تخصيص واجب منزلي إذا لزم الأمر.
- التواصل مع الطلاب بشأن كيفية إرسال الواجبات المنزلية
- وضع درجات للواجبات المنزلية.
ويمكن للمعلّمين استخدام هذه الاقتراحات بقدر ما يريدون أو بقدر ما يريدون، ويجب عدم التردد في تخصيص أي واجبات منزلية أخرى مناسبة.
إذا كنت تستخدم هذا الدرس التطبيقي بنفسك، يمكنك استخدام هذه الواجبات المنزلية لاختبار معلوماتك.
الإجابة عن هذه الأسئلة
السؤال 1
تستخدم الصفوف طريقة خاصة تعمل كمخطط لإنشاء العناصر من هذا الصف. ما اسم الطريقة؟
▢ مقاول إنشاء المباني
▢ منشئ مثيل فوري
▢ صانع البناء
▢ مخطط
السؤال 2
أي من العبارات التالية غير صحيحة عن الواجهات والصفوف التجريدية؟
▢ يمكن أن تحتوي الصفوف التجريدية على أدوات إنشاء.
▢ لا يمكن أن تتضمن الواجهات أدوات تصميم.
▢ يمكن إنشاء مثيل للواجهات والصفوف التجريدية مباشرة.
▢ يجب تطبيق الخصائص المجرّدة في الفئات الفرعية للفئة المجرّدة.
السؤال 3
أيّ مما يلي ليس مُعدِّل مستوى رؤية Kotlin للمواقع والأساليب وما إلى ذلك؟
▢ internal
▢ nosubclass
▢ protected
▢ private
السؤال 4
يمكنك وضع فئة البيانات هذه في الاعتبار:data class Fish(val name: String, val species:String, val colors:String)
أي مما يلي ليس رمزًا صالحًا لإنشاء عنصر Fish
وإزالته؟
▢ val (name1, species1, colors1) = Fish("Pat", "Plecostomus", "gold")
▢ val (name2, _, colors2) = Fish("Bitey", "shark", "gray")
▢ val (name3, species3, _) = Fish("Amy", "angelfish", "blue and black stripes")
▢ val (name4, species4, colors4) = Fish("Harry", "halibut")
السؤال 5
لنفترض أنك تمتلك حديقة حيوانات تضم الكثير من الحيوانات التي تحتاج إلى الاعتناء بها جميعًا. أيّ مما يلي لن يكون جزءًا من تنفيذ الرعاية؟
▢ interface
لأنواع مختلفة من الأطعمة التي تتناولها الحيوانات.
▢ صف abstract Caretaker
يمكنك من خلاله إنشاء أنواع مختلفة من مقدِّمي الرعاية.
▢ interface
لتوفير مياه نظيفة لحيوان
▢ صف data
لأحد الإدخالات في جدول التغذية.
انتقل إلى الدرس التالي:
للحصول على نظرة عامة على الدورة التدريبية، بما في ذلك الروابط إلى مختبرات ترميز أخرى، يُرجى الاطّلاع على "Kotlin Botcamp للمبرمجين: مرحبًا بك في الدورة التدريبية&"