Menu
CoddyTech

Duck typing

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 22 z 65.

Duck typing opiera się na tym, co obiekt potrafi zrobić, a nie na tym, do jakiej klasy należy. Jeśli ma metodę, którą wywołujesz, wywołanie działa. Nazwa pochodzi od powiedzenia „jeśli pływa jak kaczka i kwacze jak kaczka, to jest kaczką”.

Te dwie klasy nie mają wspólnego rodzica, ale obie mają metody swim() i quack():

# duck.gd
class_name Duck
extends RefCounted

func swim() -> String:
	return "Duck swimming"

func quack() -> String:
	return "Quack!"
# robot.gd
class_name Robot
extends RefCounted

func swim() -> String:
	return "Robot swimming with propellers"

func quack() -> String:
	return "Robot sound: BEEP BEEP!"

Parametr bez określonego typu akceptuje dowolny obiekt. Funkcja wywołuje metody, a każdy obiekt uruchamia własne:

func make_it_swim_and_quack(thing) -> void:
	print(thing.swim())
	print(thing.quack())
make_it_swim_and_quack(Duck.new())
make_it_swim_and_quack(Robot.new())
Duck swimming
Quack!
Robot swimming with propellers
Robot sound: BEEP BEEP!

Przesłanianie wymaga wspólnej klasy nadrzędnej; typowanie kaczego tego nie wymaga. Przy parametrze o typie thing: Duck przekazanie Robot spowodowałoby błąd parsowania.

Gdy obiekt nie ma danej metody, wywołanie zatrzymuje funkcję i powoduje błąd, taki jak Invalid call. Nonexistent function 'quack'. Najpierw zapytaj za pomocą has_method(), przekazując nazwę metody jako String:

var things := [Duck.new(), Rock.new()]
for thing in things:
	if thing.has_method("quack"):
		print(thing.quack())
	else:
		print("This one cannot quack")
Quack!
This one cannot quack

Cena: przy użyciu typów Godot znajduje nieprawidłową nazwę metody, zanim program się uruchomi; przy typowaniu strukturalnym dowiadujesz się o tym dopiero wtedy, gdy wykonywana jest dana linia. Używaj go w przypadku obiektów niepowiązanych klas, które mają kilka wspólnych metod.

challenge icon

Wyzwanie

Łatwy

Eksplozja uszkadza wszystko w pobliżu, co może otrzymywać obrażenia. Obiekty nie mają wspólnej klasy nadrzędnej. player.gd i rock.gd są gotowe: Player ma take_damage(amount) i status(), a Rock ma tylko status().

  • W pliku crate.gd dodaj klasie Crate zmienną broken, która początkowo ma wartość false, metodę take_damage(amount), która niszczy skrzynię, gdy wartość amount wynosi co najmniej 10, oraz metodę status(), która zwraca Crate: broken lub Crate: intact.
  • W pliku explosion.gd napisz statyczną metodę hit_all(things, amount). Wywołuje ona take_damage(amount) dla każdego obiektu w tablicy typu Array, który ma tę metodę, i zwraca liczbę obiektów, które trafiła.

Dostarczony kod odczytuje wiersz z nazwami obiektów (player, crate lub rock), a następnie liczbę kolejnych eksplozji i obrażenia zadawane przez każdą z nich. Wypisuje liczbę obiektów trafionych przez każdą eksplozję, a następnie status każdego obiektu. Dla player crate rock oraz eksplozji o sile 5 i 20 wypisuje:

Explosion 1 hit 2 objects
Explosion 2 hit 2 objects
Player: 75 HP
Crate: broken
Rock: solid

Twój kod umieść w plikach crate.gd i explosion.gd. Plik main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

extends Node

func _ready():
	# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
	var things := []
	for word in OS.read_string_from_stdin().split(" "):
		if word == "player":
			things.append(Player.new())
		elif word == "crate":
			things.append(Crate.new())
		else:
			things.append(Rock.new())
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var hits := Explosion.hit_all(things, int(OS.read_string_from_stdin()))
		print("Explosion %d hit %d objects" % [i + 1, hits])
	for thing in things:
		print(thing.status())
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator GDScript online