Typealias هي آلية في Kotlin لإنشاء اسم بديل لنوع موجود. تسمح الكلمة المفتاحية typealias باستبدال تعريف النوع المعقد باسم مستعار قصير وواضح دون إنشاء نوع جديد. وفقاً لتوثيق Kotlin (2026)، يحسّن typealias قابلية قراءة الكود، خاصة في تواقيع الدوال ذات الأنواع الوظيفية. Typealias يجعل الكود موثقاً ذاتياً عن طريق استبدال التعريفات المطولة بأنواع مسماة واضحة.
الملامح الرئيسية
Typealias (الاسم المستعار للنوع) هو تعريف يقدم اسماً بديلاً لنوع موجود. الصيغة: typealias الاسمالجديد = النوعالموجود. بعد التعريف، يمكن استخدام الاسمالجديد حيثما يُتوقع النوعالموجود — يعاملهما المترجم كنفس النوع. على مستوى البايت كود، لا يترك typealias أي أثر: جميع معلومات الاسم المستعار تُمحى في وقت الترجمة.
الهدف الرئيسي من typealias هو تحسين قابلية قراءة الكود. بدلاً من توقيع مطول fun process(callback: (Result) -> Unit)، يمكن كتابة typealias Callback = (Result) -> Unit واستخدام Callback كنوع المعامل. هذا مفيد بشكل خاص عندما يتكرر نفس النوع الوظيفي في عدة أماكن في الكود: يعمل الاسم المستعار كنقطة تعريف واحدة ويوثق الغرض من النوع.
Typealias لا ينشئ نوعاً جديداً — إنه مجرد مرادف. المتغيرات من نوع Callback و (Result) -> Unit قابلة للتبادل بالكامل. لن ينتج المترجم خطأ إذا تم تمرير دالة مباشرة إلى دالة تتوقع Callback. هذا يفرّق typealias عن inline class (value class)، الذي ينشئ نوعاً مغلفاً جديداً مع فحص في وقت الترجمة. Typealias هو إعادة تسمية، وليس تغليفاً.
حالة الاستخدام الأكثر شيوعاً لـ typealias في Kotlin هي الأنواع الوظيفية. التواقيع الطويلة مثل (Int, String) -> Boolean أو (List
// Without typealias
fun findUsers(
filter: (List<User>) -> List<User>
): List<User>
// With typealias
typealias UserFilter = (List<User>) -> List<User>
fun findUsers(filter: UserFilter): List<User>
// Usage in class
typealias OnClickListener = (View) -> Unit
class Button {
var onClick: OnClickListener = {}
}
في المثال، الاسم المستعار UserFilter يخفي النوع الوظيفي المعقد (List
Typealias يدعم المعاملات العامة (الأدوية)، مما يجعله أكثر مرونة. يمكن تعريف typealias Mapper
// Generic typealias
typealias Mapper<T, R> = (T) -> R
typealias Provider<T> = () -> T
typealias ListTransformer<T> = (List<T>) -> List<T>
fun processNumbers(mapper: Mapper<Int, String>) {
// mapper type is (Int) -> String
}
fun main() {
val config: Provider<String> = { "default config" }
val reverse: ListTransformer<Int> = { it.reversed() }
}
في القائمة، Mapper
الفئات المتداخلة والأنواع المعلمة الطويلة هي مجال آخر حيث يبسّط typealias الكود بشكل كبير. إذا كانت فئة عميقة في تسلسل هرمي للتداخل (Outer.Inner.Nested)، فإن الإشارة إليها بالاسم الكامل تثقل الكود. Typealias يختصر هذا الوصول ويجعله أكثر قابلية للقراءة. هذا مهم بشكل خاص للفئات من المكتبات الخارجية ذات الأسماء الطويلة.
// Alias for nested class
class NetworkResponse {
class Error(val code: Int, val message: String)
}
typealias NetworkError = NetworkResponse.Error
// Alias for long library type
typealias UserId = Long
typealias JsonMap = Map<String, Any?>
fun process(error: NetworkError) {
println("${error.code}: ${error.message}")
}
fun parseJson(data: JsonMap): UserId {
return data["id"] as? Long ?: 0L
}
في المثال، NetworkError هو اسم مستعار للفئة المتداخلة NetworkResponse.Error. باستيراد typealias، يمكن استخدام NetworkError كنوع عادي دون الكشف عن التسلسل الهرمي للتداخل. JsonMap يوثق أن الخريطة تمثل كائن JSON. UserId يوضح الغرض من Long في سياق معين — يفهم القارئ فوراً أن هذا معرف مستخدم، وليس رقماً عشوائياً. ومع ذلك، typealias لا يمنع تمرير Long عادي حيث يُتوقع UserId — لذلك يلزم value class.
Typealias و inline class (value class) يحلان مشاكل مختلفة، على الرغم من أن كلاهما يقدم اسماً جديداً لنوع. Typealias هو مجرد مرادف: متغير من نوع UserId = Long يقبل أي Long دون فحص. Inline class يغلف قيمة في نوع جديد يتم فحصه في وقت الترجمة: لا يمكن تمرير Long عادي حيث يُتوقع inline class UserId دون تحويل صريح.
| الخاصية | Typealias | Inline class |
|---|---|---|
| نوع جديد | لا — مرادف للأصل | نعم — نوع جديد مع فحوصات |
| الأداء | صفر — يُمحى بالكامل | صفر — يُزال الغلاف في البايت كود |
| الوراثة | لا | لا (فئة نهائية) |
| طرق خاصة | لا | نعم — يمكن تعريف دوال |
| أمان الأنواع | لا — قابل للتبادل مع الأصل | نعم — المترجم يميّز الأنواع |
يوضح الجدول الفرق بين الآليتين. Typealias مناسب للأسماء المختصرة وتوثيق الكود عندما لا تكون الكتابة الصارمة مطلوبة. Inline class عبر الكلمة المفتاحية value class (سابقاً inline class) ضرورية عندما يكون من المهم التمييز بين قيم مختلفة دلالياً من نفس النوع البدائي. على سبيل المثال، UserId و OrderId كلاهما Long، ولكن تمرير أحدهما حيث يُتوقع الآخر هو خطأ منطقي تمنعه value class في وقت الترجمة.
الأسئلة الشائعة
Import alias (import com.example.LongName as Short) يعمل على مستوى الاستيراد — يختصر الاسم فقط في الملف الحالي. Typealias يعلن اسماً مستعاراً عاماً متاحاً في جميع أنحاء المشروع بعد الاستيراد.
نعم، typealias يدعم التعريفات المتكررة للأنواع الوظيفية، ولكن بحذر: typealias Rec
لا، typealias يُمحى بالكامل في وقت الترجمة. يُستخدم النوع الأصلي على مستوى البايت كود ووقت التشغيل دون أي غلاف. الأداء مطابق لاستخدام النوع الأصلي مباشرة.
Typealias يمكن أن يشير إلى typealias آخر — وهذا يسمى سلسلة أسماء مستعارة. عمق السلسلة غير محدود رسمياً، ولكن من أجل القراءة يُوصى بما لا يزيد عن 2–3 مستويات. يقوم المترجم بحل السلسلة بالكامل في مرحلة التحليل.
لا، typealias هو تعريف على المستوى الأعلى أو عضو في فئة/كائن. لا يمكن تعريف typealias داخل الدوال. للاختصار المحلي للأنواع، استخدم import alias داخل الملف أو ضع typealias على مستوى الوحدة.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا