التفويض (Delegation)
جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 50 من 70.
إن تخزين object داخل object آخر ليس سوى الخطوة الأولى. تأتي القوة الحقيقية للتركيب من التفويض، عندما يمرّر object الخارجي استدعاءات method إلى مكوّناته inner.
فكّر في تشغيل سيارة. لا تمدّ يدك تحت غطاء المحرك وتدير المحرّك يدويًا. بدلًا من ذلك، تدير المفتاح، وتتولى السيارة الباقي داخليًا.
في الشيفرة، يعني هذا أن Car class توفّر طريقة :start() بسيطة تُنفّذ delegates العمل الفعلي إلى engine:
function Car:start()
print("Turning the key...")
self.engine:run() -- فوّض إلى الكائن الداخلي
endلا تحتاج السيارة إلى معرفة كيفية عمل المحرك. فهي تخبر المحرك فقط بأن يؤدي وظيفته. وهذا يُبقي المسؤوليات منفصلة. تتولى الفئة Engine منطق المحرك، بينما تنسّق Car الأجزاء:
function Engine:run()
print("Engine running at " .. self.horsepower .. " HP")
end
local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- المخرجات:
-- تدوير المفتاح...
-- المحرك يعمل بقوة 250 حصانينشئ التفويض واجهةً واضحةً لمستخدمي class الخاص بك. فهم يتفاعلون مع car، وليس مع أجزائها الداخلية. إذا استبدلت لاحقًا تنفيذًا مختلفًا لـ engine، فستظل الواجهة العامة لـ car كما هي: سيتغير التفويض الداخلي فقط.
التحدي
سهللنَبْنِ نظامًا لمشغّل موسيقى يوضّح التفويض! ستنشئ مكوّن Speaker وMusicPlayer يحتوي عليه. لن يتولى المشغّل إخراج الصوت مباشرةً، بل سيفوّض هذه المسؤولية إلى speaker الداخلي الخاص به.
ستنظّم التعليمات البرمجية عبر ثلاثة ملفات:
Speaker.lua: أنشئ فئة Speaker مع مُنشئ:new(volume)يخزّن مستوى الصوت. أدرج أسلوب:playSound(trackName)يطبع:Playing "{trackName}" at volume {volume}MusicPlayer.lua: أنشئ فئة MusicPlayer whose constructor:new(brand, speaker)تقبل اسم العلامة التجارية وكائن Speaker. يخزّن المشغّلspeakerداخله. أدرج الأساليب التالية::play(trackName): يطبع{brand} player starting...ثم يفوّض إلى أسلوب:playSound()الخاص بـspeaker:stop(): يطبع{brand} player stopped
main.lua: اجمع كل شيء معًا! اقرأ المدخلات الخاصة بمستوى صوتspeaker، والعلامة التجارية للمشغّل، واسم مقطع موسيقي. أنشئ Speaker أولًا، ثم مرّره إلى مُنشئ MusicPlayer. استدعِ أسلوب:play()الخاص بالمشغّل مع اسم المقطع، ثم استدعِ:stop().
ستتلقى ثلاثة مدخلات:
- مستوى صوت
speaker(رقم) - العلامة التجارية لمشغّل الموسيقى (سلسلة نصية)
- اسم المقطع الموسيقي المراد تشغيله (سلسلة نصية)
يجب أن يُظهر الناتج تنسيق المشغّل للعمل بالتعاون مع speaker الخاص به:
{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stoppedعلى سبيل المثال، إذا كانت المدخلات هي 75 وSoundMax وSummer Vibes، فيجب أن يكون الناتج:
SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stoppedلاحظ أن MusicPlayer لا يعرف كيف يُنتج الصوت. إنه يخبر speaker ببساطة أن يتولى ذلك الجزء. هذا هو التفويض أثناء العمل: يوفّر الكائن الخارجي واجهة واضحة، بينما ينفّذ المكوّن الداخلي العمل المتخصص!
جرّب بنفسك
-- main.lua
-- اجمع كل شيء معًا!
local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')
-- اقرأ المدخلات
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()
-- TODO: أنشئ Speaker بالحجم المعطى
-- TODO: أنشئ MusicPlayer مع brand و speaker
-- TODO: استدعِ method الـ play الخاصة بـ player مع track name
-- TODO: استدعِ method الـ stop الخاصة بـ player
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال9التركيب و Mixins
علاقة "يحتوي على" (Has-A)التفويض (Delegation)Mixins بسيطةتطبيق Mixins متعددةMixins مقابل الوراثةملخص - تجميع الروبوتتدرّب بنفسك: مترجم Lua عبر الإنترنت