Menu
CoddyTech

継承の連鎖

CoddyのGDScriptジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 18/65。

子クラス自体が親クラスになることもできます。各extendsは継承チェーンに1つのレベルを追加します。

# vehicle.gd
class_name Vehicle
extends RefCounted

var wheels: int

func _init(w: int) -> void:
	wheels = w

func describe() -> String:
	return "%d wheels" % wheels
# car.gd
class_name Car
extends Vehicle

func _init() -> void:
	super(4)

func describe() -> String:
	return "Car with " + super()
# race_car.gd
class_name RaceCar
extends Car

var top_speed: int

func _init(speed: int) -> void:
	super()
	top_speed = speed

func describe() -> String:
	return super() + ", top speed %d" % top_speed

RaceCarはCarとVehicleの両方からすべてを引き継ぎます。各super()は1段階上に進むため、1回の呼び出しでdescribe()の3つすべてのバージョンが実行されます:

print(RaceCar.new(300).describe())
Car with 4 wheels, top speed 300

メソッドを呼び出したり変数を読み取ったりすると、Godotはまずオブジェクト自身のクラスを探し、次にその親、さらに親の親を探して、最初に見つかったものを使います。RaceCar.new(300).wheelsは、2階層上のVehicleで見つかります。

すべてのクラスには親クラスが1つだけあります。extendsは1つのクラスを指定し、2つ指定すると構文解析エラーになります:

class_name FlyingCar
extends Car, Plane
Parse Error: Expected end of statement after superclass, found "," instead.

GDScriptは多重継承に対応していません。あるクラスが2つのクラスの機能を必要とする場合、それらを1つの継承チェーンにまとめるか、もう一方のクラスのオブジェクトを渡して利用します(この点については後の章で説明します)。

challenge icon

チャレンジ

簡単

character.gdには完成済みのCharacterクラスがあります。名前、hp、NAME (HP HP)を返すdescribe()、そして1を返すattack()です。これをもとに、さらに2つの階層を作りましょう。

  • WarriorはCharacterを継承し、strengthを追加します。コンストラクターでは、名前とhpをsuper()に渡します。describe()は親クラスのテキストに, strength Sを追加し、attack()はstrengthを返します。
  • KnightはWarriorを継承し、armorを追加します。コンストラクターでは、名前、hp、strengthをsuper()に渡します。describe()はWarriorのテキストに, armor Aを追加し、attack()はWarriorのattackに5を加えた値を返します。

提供されたコードは、続くキャラクターの数を読み取り、キャラクターごとに1行を読み込みます。形式はcharacter NAME HP、warrior NAME HP STRENGTH、またはknight NAME HP STRENGTH ARMORです。describe()の結果とattackを出力します。knight Arthur 120 15 8の場合、次のように出力します。

Arthur (120 HP), strength 15, armor 8
Attack: 20

コードはwarrior.gdとknight.gdに記述します。main.gdには提供された入出力コードがあり、編集できません。

自分で試してみよう

extends Node

func _ready():
	# 用意された入出力コード: そのままにしてください
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		var c: Character
		if p[0] == "knight":
			c = Knight.new(p[1], int(p[2]), int(p[3]), int(p[4]))
		elif p[0] == "warrior":
			c = Warrior.new(p[1], int(p[2]), int(p[3]))
		else:
			c = Character.new(p[1], int(p[2]))
		print(c.describe())
		print("Attack: %d" % c.attack())
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: GDScriptオンラインコンパイラ