التباين في موضع التصريح
in وout
التباين في موضع التصريح درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
مشكلة التباين
هل تُعد List<String> نوعًا من List<Any>؟ أحيانًا نعم وأحيانًا لا. يصف التباين كيفية ارتباط الأنواع العامة عندما ترتبط معاملات أنواعها. وتستخدم Kotlin كلمتي out وin للتعبير عن ذلك.
عدم التباين افتراضيًا
تكون الأنواع العامة غير متباينة افتراضيًا: فـ Box<String> ليست Box<Any>، رغم أن String نوع فرعي من Any. وهذا يمنع العمليات غير الآمنة.
class Box<T>(val value: T)
fun main() {
val strBox = Box("hi")
// val anyBox: Box<Any> = strBox // would not compile
println(strBox.value)
}التغاير باستخدام out
يؤدي تمييز معامل النوع بالكلمة out إلى جعله متغايرًا: فتصبح Producer<String> نوعًا فرعيًا من Producer<Any>. ولا يمكن أن يظهر النوع إلا في مواضع الإخراج، مثل أنواع القيم المعادة.
class Producer<out T>(private val item: T) {
fun produce(): T = item
}
fun main() {
val strProducer: Producer<String> = Producer("hello")
val anyProducer: Producer<Any> = strProducer
println(anyProducer.produce())
}لماذا يكون out آمنًا؟
إذا كانت الفئة تنتج T فقط، أي تعيده، ولا تستهلكه مطلقًا، فمن الآمن التعامل مع Producer<String> على أنه Producer<Any>، لأن كل String تعيده هو أيضًا Any.
out في المكتبة القياسية
إن List<out E> المخصصة للقراءة فقط في Kotlin متغايرة، ولذلك يمكن استخدام List<String> عندما يكون المتوقع هو List<Any>.
fun printAll(items: List<Any>) {
items.forEach { println(it) }
}
fun main() {
val names: List<String> = listOf("Ann", "Bob")
printAll(names)
}التباين العكسي باستخدام in
يؤدي تمييز معامل النوع بالكلمة in إلى جعله متباينًا عكسيًا: فتصبح Consumer<Any> نوعًا فرعيًا من Consumer<String>. ولا يمكن أن يظهر النوع إلا في مواضع الإدخال، مثل المعاملات.
class Consumer<in T> {
fun consume(item: T) {
println("Consumed $item")
}
}
fun main() {
val anyConsumer: Consumer<Any> = Consumer()
val strConsumer: Consumer<String> = anyConsumer
strConsumer.consume("hi")
}لماذا يكون in آمنًا؟
يمكن لمستهلك يقبل Any أن يقبل بالتأكيد قيمة من النوع String. لذلك يمكن استخدام Consumer<Any> في أي موضع يلزم فيه Consumer<String>.
قاعدة PECS التذكّرية
تذكّروا القاعدة: المنتج يستخدم التوسيع، والمستهلك يستخدم النوع الأعلى، أو بصياغة Kotlin: استخدموا out للمنتجين، أي للإخراج، وin للمستهلكين، أي للإدخال. فالنوع الذي يُخرج T فقط يستخدم out، والذي يُدخل T فقط يستخدم in.
الجمع بين in وout
يجب أن يظل معامل النوع المستخدم للإدخال والإخراج معًا، كما في القائمة القابلة للتغيير، غير متباين. وتوضح أنواع Function الأمرين معًا: فالمعاملات هي in، والقيمة المعادة هي out.
fun main() {
val f: (Number) -> Int = { it.toInt() }
val g: (Int) -> Number = f
println(g(3.0.let { Number::class; 5 }))
}التباين على مستوى التصريح يعني موضعًا واحدًا
يُعلن التباين على مستوى التصريح مرة واحدة في الفئة نفسها باستخدام in/out. وبعد ذلك يرث كل استخدام للفئة التباين تلقائيًا، بخلاف Java حيث تكرر أحرف البدل عند كل استخدام.
اختيار in أو out
اسأل نفسك: هل تنتج هذه الفئة T فقط، فاستخدم out، أم تستهلك T فقط، فاستخدم in، أم تفعل الأمرين معًا، فاتركها غير متباينة؟ إن مطابقة المعدِّل لدور النوع تجعل الأنواع العامة مرنة وآمنة.
تحقق سريع
إلى ماذا يشير المعدِّل out؟
مراجعة
الأنواع العامة غير متباينة افتراضيًا. استخدموا out للتغاير عندما ينتج النوع القيم فقط، وin للتباين العكسي عندما يستهلك النوع القيم فقط. تذكّروا أن المنتجين يستخدمون out، والمستهلكين يستخدمون in. بعد ذلك ستطبقون التباين عند موضع الاستخدام باستخدام إسقاطات الأنواع.
الأسئلة الشائعة
هل درس «التباين في موضع التصريح» مجاني؟
نعم — نص درس «التباين في موضع التصريح» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ماذا ستتعلم في «التباين في موضع التصريح»؟
in وout تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟
لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «التباين في موضع التصريح»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟
نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الدوال والفئات العامة
- التباين في موضع التصريح
- التباين في موضع الاستخدام
- قيود الأنواع العامة