Menu
CoddyTech

Kompozycja a dziedziczenie

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

Klasy ponownie wykorzystują kod na dwa sposoby. Dziedziczenie (extends) oznacza, że klasa jest rodzajem innej klasy: Mage jest Player. Kompozycja oznacza, że klasa ma część: przechowuje inny obiekt w zmiennej składowej i przekazuje mu pracę:

# motor.gd
class_name Motor
extends RefCounted

func start() -> String:
	return "motor running"

# car.gd
class_name Car
extends RefCounted

var motor := Motor.new()

func start() -> String:
	return "Car starts, " + motor.start()

Car.new().start() zwraca Car starts, motor running. Samochód nie wie, jak działa silnik: wywołuje motor.start(). Przekazywanie wywołania do takiej części nazywa się delegowaniem. (Klasa nosi nazwę Motor, ponieważ Engine jest już klasą Godot.)

Kompozycja się opłaca, gdy części się zmieniają lub łączą. W przypadku dziedziczenia postać chodząca i postać latająca to dwie podklasy, a nietoperz, który zaczyna latać, nie może zmienić swojej klasy. W przypadku kompozycji postać ma część odpowiedzialną za ruch, a jej zmiana wymaga tylko jednego przypisania:

# character.gd
class_name Character
extends RefCounted

var char_name: String
var movement: Movement

func _init(new_name: String, new_movement: Movement) -> void:
	char_name = new_name
	movement = new_movement

func move() -> String:
	return char_name + " " + movement.move()

# main.gd
var bat := Character.new("Bat", Walk.new())
print(bat.move()) # Bat chodzi
bat.movement = Fly.new()
print(bat.move()) # Bat lata

Tutaj Walk i Fly rozszerzają małą klasę Movement: te dwie techniki działają razem. Klasa GDScript może extend tylko jedną klasę, więc kompozycja to także sposób, w jaki jeden obiekt zyskuje kilka umiejętności, przechowując kilka części.

Używaj dziedziczenia w przypadku rzeczywistej relacji „jest czymś”, która nigdy się nie zmienia. Używaj kompozycji, gdy klasa „ma” coś albo gdy część musi być wymieniana podczas działania gry.

challenge icon

Wyzwanie

Łatwy

Rycerz nie dziedziczy po broni: rycerz ma broń i może ją zmieniać. Zbuduj obie klasy.

  • Weapon przechowuje weapon_name i damage, oba ustawiane przez konstruktor: Weapon.new("Sword", 7).
  • Knight przechowuje knight_name (z konstruktora) oraz broń, która na początku ma wartość null.
  • equip(new_weapon) zastępuje broń, a drop() ustawia ją z powrotem na null.
  • attack() zwraca Ada attacks with Sword for 7 damage, używając imienia rycerza oraz nazwy i obrażeń broni, albo Ada has no weapon, gdy rycerz nie ma broni.

Dostarczony kod odczytuje imię rycerza i liczbę następujących po nim poleceń (equip Sword 7, drop, attack), a następnie je wykonuje. Dla Ada i poleceń attack, equip Sword 7, attack, equip Axe 12, attack, drop, attack wypisuje:

Ada has no weapon
Equipped Sword
Ada attacks with Sword for 7 damage
Equipped Axe
Ada attacks with Axe for 12 damage
Dropped the weapon
Ada has no weapon

Twój kod umieść w plikach weapon.gd i knight.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 knight := Knight.new(OS.read_string_from_stdin())
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "equip":
			knight.equip(Weapon.new(parts[1], int(parts[2])))
			print("Equipped ", parts[1])
		elif parts[0] == "drop":
			knight.drop()
			print("Dropped the weapon")
		else:
			print(knight.attack())
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