Kotlin Academy · درس

محو النوع ومعاملات النوع reified

استخدم reified مع الدوال inline للوصول إلى معلومات النوع وقت التشغيل.

الدرس 4 من 414 خطوة

محو النوع ومعاملات النوع reified درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ما محو الأنواع؟

يمحو JVM معاملات الأنواع العامة أثناء التشغيل. فكل من List<String> وList<Int> يصبح ببساطة List. وهذا يحدّ من عمليات الأنواع أثناء التشغيل على الأنواع العامة.

fun main() {
    val strings: List<String> = listOf("a", "b")
    val ints: List<Int> = listOf(1, 2)
    println(strings.javaClass == ints.javaClass) // true: both ArrayList
    println(strings is List<*>)  // OK with star
    // println(strings is List<String>) // warning: unchecked cast
}

المشكلة: لا يمكن فحص الأنواع الممحوة

لا يمكنك استخدام is مع معامل نوع عام محدد، لأن معلومات النوع تختفي أثناء التشغيل.

fun checkType(obj: Any) {
    // This works:
    if (obj is List<*>) println("It's a list of something")
    // This doesn't compile cleanly:
    // if (obj is List<String>) println("It's a list of strings") // unchecked
}
fun main() {
    checkType(listOf("hello"))
    checkType(42)
}

مراجعة دوال inline

تنسخ inline جسم الدالة إلى موضع الاستدعاء أثناء الترجمة. وهذا ما يتيح reified — إذ يُستبدل معامل النوع أيضًا في موضع الاستدعاء.

inline fun <T> myRun(block: () -> T): T = block()
fun main() {
    val result = myRun { 42 }
    println(result) // 42
    // The compiler inlines the lambda body — no object allocation
}

reified: الوصول إلى T أثناء التشغيل

يؤدي الجمع بين inline وreified إلى الحفاظ على معامل النوع في موضع الاستدعاء، مما يتيح استخدام is وas و::class مع T.

inline fun <reified T> isInstance(value: Any): Boolean = value is T
fun main() {
    println(isInstance<String>("hello"))  // true
    println(isInstance<Int>("hello"))     // false
    println(isInstance<List<*>>(listOf())) // true
}

الحصول على KClass لـ T

باستخدام reified T، يمكنك الحصول على T::class أثناء التشغيل — وهو أمر مستحيل عادةً في الدوال العامة.

inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
    println(classNameOf<String>())   // String
    println(classNameOf<Int>())      // Int
    println(classNameOf<List<*>>())  // List
}

تحويل آمن باستخدام reified

استخدم reified لكتابة أداة تحويل آمنة للأنواع تُرجع قيمة فارغة بدلًا من إطلاق استثناء.

inline fun <reified T> Any?.safeCast(): T? = this as? T
fun main() {
    val obj: Any = "Hello"
    val s: String? = obj.safeCast<String>()
    val i: Int? = obj.safeCast<Int>()
    println(s) // Hello
    println(i) // null
}

تحليل JSON باستخدام reified

تستخدم مكتبات مثل Gson أو kotlinx.serialization ميزة reified لاستنتاج النوع المستهدف في موضع الاستدعاء دون تمرير كائنات Class صراحةً.

import com.google.gson.Gson
// Simulated without real Gson:
inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java)
}
// Usage:
// val user: User = parseJson<User>("""{"name":"Alice"}""")

reified مع filterIsInstance

تستخدم الدالة filterIsInstance<T>() في المكتبة القياسية ميزة reified لتصفية قائمة وفق نوع محدد دون تحويل يدوي للأنواع.

fun main() {
    val mixed: List<Any> = listOf(1, "hello", 2.5, "world", true)
    val strings = mixed.filterIsInstance<String>()
    val ints = mixed.filterIsInstance<Int>()
    println(strings) // [hello, world]
    println(ints)    // [1]
}

لا يمكن استخدام reified في دوال غير inline

تعمل reified فقط مع دوال inline. وتؤدي محاولة استخدامها دون inline إلى خطأ في الترجمة.

// Error:
// fun <reified T> broken(): String = T::class.simpleName ?: "?"

// Must be inline:
inline fun <reified T> correct(): String = T::class.simpleName ?: "?"
fun main() {
    println(correct<Double>()) // Double
}

reified والانعكاس

اجمع بين reified والانعكاس لفحص خصائص النوع أو تعليقاته التوضيحية ديناميكيًا دون معاملات Class زائدة.

inline fun <reified T : Any> properties(): List<String> =
    T::class.members.map { it.name }
data class Point(val x: Int, val y: Int)
fun main() {
    println(properties<Point>()) // [x, y, component1, component2, copy, equals, hashCode, toString]
}

تطبيقي: محدد مواقع الخدمات الآمن للأنواع

استخدم reified لإنشاء محدد مواقع خدمات يربط KClass بالنسخ، وذلك لتوفير DI خفيف الوزن دون معالجات التعليقات التوضيحية.

val registry = mutableMapOf<kotlin.reflect.KClass<*>, Any>()
inline fun <reified T : Any> register(instance: T) { registry[T::class] = instance }
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> resolve(): T = registry[T::class] as T
class Logger { fun log(msg: String) = println("[LOG] $msg") }
fun main() {
    register(Logger())
    resolve<Logger>().log("Service located!")
}

قيود reified

لا يمكن استخدام معاملات النوع reified في سياقات غير inline، ولا يمكن تخزين النوع لاستخدامه لاحقًا، ولا تمريره إلى دوال غير inline تحتاج إلى النوع أثناء التشغيل.

inline fun <reified T> foo() {
    val clazz = T::class // OK here
    // bar(clazz)        // must pass clazz explicitly to non-inline funs
    println(clazz.simpleName)
}
fun bar(clazz: kotlin.reflect.KClass<*>) = println(clazz.simpleName)
fun main() { foo<String>() }

اختبار سريع

ما المطلوب لكي يكون معامل النوع reified؟

مراجعة

يزيل محو الأنواع معلومات الأنواع العامة أثناء التشغيل. وتحافظ reified في دوال inline على معامل النوع في موضع الاستدعاء، مما يتيح استخدام is وas و::class والانعكاس على T — دون تمرير كائنات Class يدويًا.

البدء مجانًا

تعلم Kotlin مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
51
الدروس
203

الأسئلة الشائعة

هل درس «محو النوع ومعاملات النوع reified» مجاني؟

نعم — نص درس «محو النوع ومعاملات النوع reified» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «محو النوع ومعاملات النوع reified»؟

استخدم reified مع الدوال inline للوصول إلى معلومات النوع وقت التشغيل. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «محو النوع ومعاملات النوع reified»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الدوال العامة وقيود الأنواع باستخدام where
  2. التباين في موضع التصريح: ‏in وout
  3. إسقاط النجمة ومتى تستخدم *
  4. محو النوع ومعاملات النوع reified
← العودة إلى Kotlin Academy