Menu
CoddyTech

Composizione vs ereditarietà

Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 40 di 65.

Le classi riutilizzano il codice in due modi. L'ereditarietà (extends) indica che una classe è un tipo di un'altra classe: un Mage è un Player. La composizione indica che una classe ha una parte: memorizza un altro oggetto in una variabile membro e gli delega il lavoro:

# 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() restituisce Car starts, motor running. L'auto non sa come funziona un motore: chiama motor.start(). Affidare una chiamata a una parte in questo modo si chiama delegazione. (La classe si chiama Motor perché Engine è già una classe di Godot.)

La composizione ripaga quando le parti cambiano o si combinano. Con l'ereditarietà, un personaggio che cammina e un personaggio che vola sono due sottoclassi, e un pipistrello che inizia a volare non può cambiare classe. Con la composizione, il personaggio ha una parte dedicata al movimento, e sostituirla richiede una sola assegnazione:

# 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 walks
bat.movement = Fly.new()
print(bat.move()) # Bat flies

Qui Walk e Fly estendono una piccola classe Movement: le due tecniche funzionano insieme. Una classe GDScript può extend una sola classe, quindi la composizione è anche il modo in cui un oggetto acquisisce diverse abilità, contenendo diverse parti.

Usa l'ereditarietà per una relazione «è un» reale che non cambia mai. Usa la composizione quando la classe «ha» qualcosa o quando la parte deve essere sostituita mentre il gioco è in esecuzione.

challenge icon

Sfida

Facile

Un cavaliere non eredita da un'arma: un cavaliere ha un'arma e può cambiarla. Crea entrambe le classi.

  • Weapon memorizza weapon_name e damage, entrambi impostati dal costruttore: Weapon.new("Sword", 7).
  • Knight memorizza knight_name (dal costruttore) e un'arma, che all'inizio è null.
  • equip(new_weapon) sostituisce l'arma e drop() la reimposta a null.
  • attack() restituisce Ada attacks with Sword for 7 damage, usando il nome del cavaliere e il nome e i danni dell'arma, oppure Ada has no weapon quando non ce n'è una.

Il codice fornito legge il nome del cavaliere e il numero di comandi che seguono (equip Sword 7, drop, attack) e li esegue. Per Ada e attack, equip Sword 7, attack, equip Axe 12, attack, drop, attack stampa:

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

Il tuo codice va in weapon.gd e knight.gd. main.gd contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

extends Node

func _ready():
	# Supplied input/output code: keep it as it is
	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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore GDScript online