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 quackCena: 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.
Wyzwanie
ŁatwyEksplozja 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.gddodaj klasieCratezmiennąbroken, która początkowo ma wartośćfalse, metodętake_damage(amount), która niszczy skrzynię, gdy wartość amount wynosi co najmniej10, oraz metodęstatus(), która zwracaCrate: brokenlubCrate: intact. - W pliku
explosion.gdnapisz statyczną metodęhit_all(things, amount). Wywołuje onatake_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: solidTwó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())
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe selfMetodyWłaściwościKonstruktor (_init)Powtórka – prosty kalkulator4Polimorfizm
Ponowne omówienie przesłaniania metodDuck typingKlasy i metody abstrakcyjneProjektowanie interfejsówPowtórzenie – kalkulator kształtów7Sygnały
Czym jest sygnał?Deklarowanie i emitowanieŁączenie z sygnałamiSygnały z argumentamiPodsumowanie — system zdrowia10Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu2Właściwości klas
Zmienne instancji a zmienne statyczneFunkcje statyczneSettery właściwościGettery właściwościPrywatne z konwencjiPodsumowanie — menedżer kont bankowych5Enkapsulacja
Elementy publiczne i prywatneWalidacja za pomocą setterówUkrywanie informacjiWłaściwości tylko do odczytuPodsumowanie – system ewidencji uczniów8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieKlasy wewnętrzneWęzły jako komponentyRefCounted a NodeTypy wyliczeniowe w klasach11Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superNadpisywanie metodŁańcuchy dziedziczeniaSprawdzanie typów za pomocą isPodsumowanie – hierarchia pracowników6Metody specjalne
Wprowadzenie do metod wirtualnychMetoda _to_stringWłasne iteratoryPodsumowanie — własna lista9Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator GDScript online