التفويض مقابل الوراثة
اختاروا التركيب
التفويض مقابل الوراثة درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
طريقتان لإعادة الاستخدام
يعيد كل من التوريث والتفويض استخدام السلوك. يقول التوريث إن الفئة هي نوع من فئة أخرى. أما التفويض فيقول إن الفئة تمتلك كائنًا متعاونًا توجّه إليه الاستدعاءات.
والنصيحة التقليدية هي: فضّل التركيب على التوريث.
مثال على التوريث
في التوريث، توسّع الفئة الفرعية فئة أساسية وتعيد تعريف الأعضاء. ويجب أن تكون الفئة الأساسية open في Kotlin.
open class Animal {
open fun sound() = "..."
}
class Dog : Animal() {
override fun sound() = "woof"
}
fun main() {
println(Dog().sound())
}مثال على التفويض
إعادة الاستخدام نفسها مع التفويض: يكون السلوك موجودًا في عضو تُحيل إليه الفئة.
interface Sound { fun sound(): String }
class Bark : Sound { override fun sound() = "woof" }
class Dog(s: Sound) : Sound by s
fun main() {
println(Dog(Bark()).sound())
}الفئة الأساسية الهشّة
تربط الوراثة الفئة الفرعية ارتباطًا وثيقًا بالتفاصيل الداخلية للفئة الأب. وقد يؤدي تغيير في الفئة الأساسية إلى كسر الفئات الفرعية بصمت — وهذه هي مشكلة الفئة الأساسية الهشّة. أما التفويض فلا يعتمد إلا على الواجهة.
التغليف
يمكن للفئة الفرعية الوصول إلى الأعضاء المحمية وتجاوز نقاط التوسعة، فتتطلع إلى داخل الفئة الأب. أما الفئة التي تستخدم التفويض فلا ترى إلا الواجهة العامة، مما يحافظ على التغليف.
interface Counter { fun increment(): Int }
class SimpleCounter : Counter {
private var n = 0
override fun increment(): Int { n++; return n }
}
class GuardedCounter(private val c: Counter) : Counter by c {
override fun increment(): Int {
println("incrementing")
return c.increment()
}
}
fun main() {
val g = GuardedCounter(SimpleCounter())
println(g.increment())
println(g.increment())
}المرونة في وقت التشغيل
تحدد الوراثة الفئة الأب في وقت الترجمة. أما التفويض فيتيح حقن تطبيقات مختلفة في وقت التشغيل، مما يدعم الاختبار السهل باستخدام تطبيقات وهمية.
interface Clock { fun now(): Int }
class RealClock : Clock { override fun now() = 100 }
class FakeClock : Clock { override fun now() = 0 }
class Timer(c: Clock) : Clock by c
fun main() {
println(Timer(RealClock()).now())
println(Timer(FakeClock()).now()) // easy to test
}سلوكيات متعددة
يمكن للفئة توسيع فئة أب واحدة فقط، لكنها تستطيع التفويض إلى واجهات متعددة. ويتوسع التفويض لضم عدة إمكانات.
interface Walk { fun walk() = "walking" }
interface Swim { fun swim() = "swimming" }
class Walker : Walk
class Swimmer : Swim
class Amphibian : Walk by Walker(), Swim by Swimmer()
fun main() {
val a = Amphibian()
println(a.walk() + ", " + a.swim())
}متى تناسب الوراثة
تظل الوراثة مناسبة لعلاقة is-a حقيقية ضمن تسلسل هرمي مستقر ومصمم للتوسعة، مثل عائلات الأنواع المغلقة، والفئات الأساسية لأطر العمل، وتعدد الأشكال على نوع مجرد مشترك.
sealed class Shape
class Circle(val r: Double) : Shape()
class Square(val s: Double) : Shape()
fun area(shape: Shape) = when (shape) {
is Circle -> 3.14 * shape.r * shape.r
is Square -> shape.s * shape.s
}
fun main() {
println(area(Circle(2.0)))
}متى يناسب التفويض
اختر التفويض عندما تريد:
- إعادة استخدام السلوك بين أنواع غير مترابطة
- ضم إمكانات متعددة
- الحفاظ على اقتران منخفض واختبار سهل
- تغليف التطبيقات الحالية وتزيينها
مقارنة جنبًا إلى جنب
الوراثة: أب واحد، اقتران وثيق، ثابتة في وقت الترجمة، is-a. التفويض: متعاونون متعددون، اقتران ضعيف، قابلون للاستبدال في وقت التشغيل، has-a. تجعل Kotlin التفويض منخفض التكلفة باستخدام by، مما يرجح كفة التركيب.
خيار افتراضي عملي
قاعدة جيدة: ابدأ بالتفويض. انتقل إلى الوراثة فقط عندما يظهر تسلسل هرمي حقيقي ومستقر لعلاقة is-a. يحافظ ذلك على مرونة التصميمات وقدرتها على مقاومة التغييرات.
تحقق سريع
اختبر فهمك للتفويض مقارنةً بالوراثة.
مراجعة
قارنت بين النهجين:
- الوراثة: is-a، أب واحد، اقتران وثيق
- التفويض: has-a، متعاونون متعددون، اقتران ضعيف
- فضّل التركيب؛ واستخدم الوراثة للتسلسلات الهرمية المستقرة من نوع is-a
التالي: أنماط المزيّن العملية باستخدام التفويض.
الأسئلة الشائعة
هل درس «التفويض مقابل الوراثة» مجاني؟
نعم — نص درس «التفويض مقابل الوراثة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.
ماذا ستتعلم في «التفويض مقابل الوراثة»؟
اختاروا التركيب تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟
لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «التفويض مقابل الوراثة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟
نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الكلمة المفتاحية by
- التفويض إلى الأعضاء
- التفويض مقابل الوراثة
- أنماط عملية