Menu
CoddyTech

メソッドのオーバーライド再訪

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

ポリモーフィズムとは「多くの形」を意味します。1つのメソッド呼び出しが、それを受け取るオブジェクトのクラスに応じて異なる処理を行います。オーバーライドによってこれが可能になります。

# animal.gd
class_name Animal
extends RefCounted

func speak() -> String:
	return "..."
# dog.gd
class_name Dog
extends Animal

func speak() -> String:
	return "Woof!"
# cat.gd
class_name Cat
extends Animal

func speak() -> String:
	return "Meow!"

Array[Animal]には、それらすべてを格納できます。ループは各要素がどのクラスに属するかを知らずにspeak()を呼び出し、各オブジェクトはそれぞれ独自のバージョンで応答します:

var animals: Array[Animal] = [Dog.new(), Cat.new(), Animal.new()]
for animal in animals:
	print(animal.speak())
Woof!
Meow!
...

Animalパラメーターを持つ関数も同じように動作します。後から追加するクラスも含め、すべての子クラスを変更なしで受け付けます。

func make_it_speak(animal: Animal) -> void:
	print("It says ", animal.speak())
make_it_speak(Cat.new())
It says Meow!

これをクラスを一つずつ確認する方法と比べてみましょう。if animal is Dog:の分岐は、新しいクラスが増えるたびに追加する必要があります。オーバーライドを使えば、各クラスが独自の振る舞いを持ち、それを呼び出すコードは変わりません。

challenge icon

チャレンジ

簡単

ガレージでは、すべての車両を1つのArray[Vehicle]で扱います。vehicle.gdでは、wheels()は0を返し、sound()は...を返します。

  • Vehicleにdescribe()を書きます。これはwheels()とsound()を呼び出し、BRAND: N wheels, SOUNDを返します。
  • Carはwheels()を4で、sound()をVroomでオーバーライドします。
  • Motorcycleは、それぞれ2とBrrmでオーバーライドします。
  • Truckには、トレーラーの数を格納するtrailersがすでにあります。wheels()はトレーラー1台につき6に4を加えた値で、sound()はHonkでオーバーライドします。

子クラスはdescribe()をオーバーライドしません。用意されているコードは、続く車両の数を読み取ったあと、車両ごとに1行を読み取ります。形式はcar BRAND、motorcycle BRAND、truck BRAND TRAILERS、またはvehicle BRANDです。各車両のdescribe()の結果と、wheels()の合計を出力します。car Toyotaとtruck Volvo 2の場合、次のように出力します。

Toyota: 4 wheels, Vroom
Volvo: 14 wheels, Honk
Total wheels: 18

コードはvehicle.gd、car.gd、motorcycle.gd、truck.gdに記述します。main.gdには用意された入出力コードが含まれており、編集できません。

自分で試してみよう

extends Node

func _ready():
	# 提供された入出力コード: そのままにしてください
	var count := int(OS.read_string_from_stdin())
	var vehicles: Array[Vehicle] = []
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		if p[0] == "car":
			vehicles.append(Car.new(p[1]))
		elif p[0] == "motorcycle":
			vehicles.append(Motorcycle.new(p[1]))
		elif p[0] == "truck":
			vehicles.append(Truck.new(p[1], int(p[2])))
		else:
			vehicles.append(Vehicle.new(p[1]))
	var total := 0
	for v in vehicles:
		print(v.describe())
		total += v.wheels()
	print("Total wheels: %d" % total)
quiz icon腕試し

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

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

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