نمط المحوّل
جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 51 من 65.
يتيح نمط المحوّل لكائنٍ ما العمل مع شيفرة تتوقع أساليب مختلفة. يغلّف المحوّل الكائن ويحوّل كل استدعاء متوقع إلى استدعاء يفهمه الكائن.
يخزّن صنف قديم من مشروع سابق الصحة على شكل رقمين:
# old_monster.gd
class_name OldMonster
extends RefCounted
var life := 30
var max_life := 120تعرض واجهة HUD أي شيء لديه get_label() وget_hp_percent(). لدى Knight كليهما بالفعل (فهو يُرجع "Knight" و80)، لكن OldMonster لا يملك أيًا منهما:
# health_display.gd
class_name HealthDisplay
extends RefCounted
func show_health(target) -> void:
print(target.get_label(), ": ", target.get_hp_percent(), "%")يحتفظ المحوِّل بكائن OldMonster ويوفّر الطريقتين اللتين تستدعيهما شاشة العرض:
# monster_adapter.gd
class_name MonsterAdapter
extends RefCounted
var monster: OldMonster
func _init(wrapped: OldMonster) -> void:
monster = wrapped
func get_label() -> String:
return "Monster"
func get_hp_percent() -> int:
return monster.life * 100 / monster.max_life# main.gd
var display := HealthDisplay.new()
display.show_health(Knight.new())
display.show_health(MonsterAdapter.new(OldMonster.new()))Knight: 80%
Monster: 25%لم يتغير كلٌّ من OldMonster وHealthDisplay. وهذا مهم عندما لا تستطيع تعديل فئة أو لا ينبغي لك ذلك: فقد جاءت من إضافة، أو كان فريق آخر مسؤولًا عنها، أو كانت نصوص برمجية كثيرة تعتمد على أسمائها.
يمرّر المحوِّل كل استدعاء ويحوّل البيانات أثناء ذلك، وهنا يحوّل رقمين إلى نسبة مئوية واحدة. اضرب قبل القسمة: عند استخدام الأعداد الصحيحة، تكون 30 / 120 * 100 مساوية لـ 0، بينما تكون 30 * 100 / 120 مساوية لـ 25.
التحدي
سهلتعرض لوحة الطقس مستشعرات لديها get_sensor_name() وget_celsius()، مثل ModernSensor (modern_sensor.gd). توجد اللوحة في weather_board.gd. لا تتيح موازين الحرارة القديمة (legacy_thermometer.gd) سوى read_fahrenheit() وget_code(). اكتب المحوّل ThermometerAdapter:
- يخزّن المُنشئ كائن
LegacyThermometerالذي يغلّفه. - تعيد
get_sensor_name()القيمةThermometer، متبوعة بمسافة ورمز مقياس الحرارة، مثلThermometer TH-4. - تعيد
get_celsius()درجة الحرارة بالدرجة المئوية:(fahrenheit - 32) * 5 / 9، على هيئةfloat.
لا تغيّر الفئات الأخرى. يقرأ الكود المزوّد عدد المستشعرات التي تليه، ثم مستشعرًا واحدًا في كل سطر: legacy ID FAHRENHEIT أو modern NAME CELSIUS. وهو يغلّف كل مقياس حرارة قديم باستخدام المحوّل الذي تكتبه، ثم يعرض جميع المستشعرات. بالنسبة إلى legacy 4 98.6 وmodern Garden 21.5 يكون الناتج:
Thermometer TH-4: 37.0 C
Garden: 21.5 C
Warmest: Thermometer TH-4ضع الكود في thermometer_adapter.gd. يحتوي main.gd على كود الإدخال/الإخراج المزوّد ولا يمكن تعديله.
جرّب بنفسك
extends Node
func _ready():
# شيفرة الإدخال/الإخراج المقدَّمة: اتركها كما هي
var board := WeatherBoard.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "legacy":
var old := LegacyThermometer.new(int(parts[1]), float(parts[2]))
board.add_sensor(ThermometerAdapter.new(old))
else:
board.add_sensor(ModernSensor.new(parts[1], float(parts[2])))
board.show_all()
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجّه
1أساسيات البرمجة كائنية التوجه
الملفات الخارجيةمقدمة إلى البرمجة كائنية التوجهالفئات مقابل الكائناتالكلمة المفتاحية selfالأساليبالخصائصالمُنشئ (_init)مراجعة - آلة حاسبة بسيطة4تعدد الأشكال
إعادة النظر في تجاوز الأساليبكتابة الأنواع بأسلوب البطةالفئات والأساليب المجرّدةتصميم الواجهاتمراجعة - حاسبة الأشكال10أنماط التصميم، الجزء الثاني
نمط الأوامرنمط المحوّلنمط المُزيّننمط الطريقة القالبيةنمط الحالةالنمط المركّب2خصائص الأصناف
متغيرات الكائن مقابل المتغيرات الساكنةالدوال الساكنةمُعيِّنات الخصائصمُسترجِعات الخصائصخاص وفقًا للاتفاقيةمراجعة - مدير الحسابات البنكية5التغليف
الأعضاء العامة والخاصةالتحقق من الصحة باستخدام دوال الضبطإخفاء المعلوماتالخصائص للقراءة فقطمراجعة - نظام سجلات الطلاب8مفاهيم متقدمة في البرمجة كائنية التوجه
التركيب مقابل الوراثةالأصناف الداخليةالعُقد كمكوّناتRefCounted مقابل Nodeالتعدادات في الأصنافتدرّب بنفسك: مترجم GDScript عبر الإنترنت