Menu
CoddyTech

מבוא למתודות וירטואליות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GDScript של Coddy. שיעור 31 מתוך 65.

ל-Python יש שיטות קסם כמו __init__ ו-__str__, שהשפה קוראת להן עבורך. ב-Godot המקבילה היא שיטה וירטואלית: שיטה בעלת שם קבוע, שמתחיל בקו תחתון, שאותה מגדירים במחלקה שלך ו-Godot קוראת לה ברגע המתאים. כבר השתמשת בשתיים:

  • _init() מופעלת כאשר new() יוצר את האובייקט, עם הארגומנטים שניתנו ל-new().
  • _ready() מופעלת כאשר צומת נכנס לעץ הסצנה, ושם main.gd מתחיל.

אחרות הן _to_string(), שנקראת כשמדפיסים אובייקט, שיטות האיטרטור שמאפשרות ללולאת for לעבור על אובייקט (שתיהן יופיעו בשיעורים הבאים), ו-_notification(), שמקבלת אירועים מהמנוע. אחת מהן, NOTIFICATION_PREDELETE, מתקבלת ממש לפני מחיקת האובייקט:

# torch.gd
class_name Torch
extends RefCounted

var label: String

func _init(new_label: String = "Torch") -> void:
	label = new_label
	print(label, " lit")

func _notification(what: int) -> void:
	if what == NOTIFICATION_PREDELETE:
		print(label, " burned out")
# main.gd
var torch := Torch.new("Hall torch") # הלפיד במסדרון דולק
torch = null # הלפיד במסדרון כבה

אובייקט מסוג RefCounted נמחק ברגע שאף משתנה אינו מפנה אליו עוד, ולכן torch = null שולח את ההתראה מיד. ערך ברירת המחדל ב־_init() הופך את הארגומנט של new() לאופציונלי: Torch.new() יוצר לפיד בשם Torch.

גם Python משתמשת בשיטות קסם עבור אופרטורים, כגון __add__ עבור + ו־__eq__ עבור ==. ב־GDScript אין העמסת אופרטורים: potion_a + potion_b היא שגיאה. כתוב במקום זאת שיטה:

# potion.gd
class_name Potion
extends RefCounted

var power: int

func _init(start_power: int) -> void:
	power = start_power

func combined(other: Potion) -> Potion:
	return Potion.new(power + other.power)

potion_a.combined(potion_b) מחזירה שיקוי חדש ומשאירה את שני השיקויים המקוריים ללא שינוי. == בין שני אובייקטים בודק אם שני הצדדים הם אותו אובייקט עצמו, ולא אם הערכים שלהם תואמים: Potion.new(5) == Potion.new(5) הוא false. כתוב מתודה כמו equals(other) כשצריך להשוות ערכים.

challenge icon

אתגר

קל

כתבו את המחלקה Counter בקובץ counter.gd:

  • _init(start = 0, step_size = 1) שומרת את ערך ההתחלה ב-value ואת גודל הצעד ב-step. ערכי ברירת המחדל כבר מופיעים בחתימה, ולכן Counter.new(), Counter.new(5) וגם Counter.new(5, 2) פועלים.
  • tick() מוסיפה את step ל-value.
  • plus(other) מחליפה את האופרטור +, שאי אפשר להגדיר ב-GDScript: היא מחזירה Counter חדש, שהערך שלו הוא סכום שני הערכים והצעד שלו הוא הצעד של מונה זה. אף אחד מהמונהים אינו משתנה.
  • equals(other) מחזירה true כאשר לשני המונים יש אותו ערך.

הקוד שסופק קורא שתי שורות שיוצרות את המונים a ו-b (שורה ריקה, START או START STEP), ואז שורה אחת עם מספר הפעמים שיש לבצע תקתוק עבור a ועבור b. הוא מדפיס את שני המונים, את הסכום שלהם, האם הערכים שלהם שווים והאם a == b. עבור השורות 5, 2 3 ו-3 1 הוא מדפיס:

a: 8 (step 1)
b: 5 (step 3)
a plus b: 13 (step 1)
same value: false
same object: false

כתבו את הקוד שלכם ב-counter.gd. הקובץ main.gd מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

extends Node

func _ready():
	# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
	var a := make_counter(OS.read_string_from_stdin())
	var b := make_counter(OS.read_string_from_stdin())
	var ticks := OS.read_string_from_stdin().split(" ")
	for i in int(ticks[0]):
		a.tick()
	for i in int(ticks[1]):
		b.tick()
	print("a: %d (step %d)" % [a.value, a.step])
	print("b: %d (step %d)" % [b.value, b.step])
	var total := a.plus(b)
	print("a plus b: %d (step %d)" % [total.value, total.step])
	print("same value: %s" % a.equals(b))
	print("same object: %s" % (a == b))

func make_counter(line: String) -> Counter:
	var parts := line.split(" ", false)
	if parts.is_empty():
		return Counter.new()
	if parts.size() == 1:
		return Counter.new(int(parts[0]))
	return Counter.new(int(parts[0]), int(parts[1]))
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר GDScript אונליין