Menu
CoddyTech
flag Ar iconالعربيةdown icon

نمط المحوّل

جزء من قسم البرمجة كائنية التوجّه في رحلة 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.

challenge icon

التحدي

سهل

تعرض لوحة الطقس مستشعرات لديها 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()
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجّه

تدرّب بنفسك: مترجم GDScript عبر الإنترنت