Menu
CoddyTech

インターフェース設計

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

インターフェースとは、クラスが実装することを約束するメソッドの一覧で、メソッドのコードは含まれません。Java と C# にはinterfaceキーワードがありますが、GDScript にはありません。すべてのメソッドが抽象メソッドである抽象クラスを使って、同じものを作ります。

# drawable.gd
@abstract
class_name Drawable
extends RefCounted

@abstract func draw() -> String
@abstract func resize(factor: int) -> void

変数もメソッド本体もありません。描画可能なものが何をできるかを記述し、その方法は各クラスが決めます。

# banner.gd
class_name Banner
extends Drawable

var text: String
var size := 1

func _init(t: String) -> void:
	text = t

func draw() -> String:
	return "Banner '%s' at size %d" % [text, size]

func resize(factor: int) -> void:
	size *= factor

Circle も Drawable を拡張でき、radius と独自の draw() および resize() を持ちます。このインターフェースを使うコードはインターフェースのみに依存するため、後から作成されたものも含め、Drawable を拡張するすべてのクラスで動作します。

func render_all(items: Array[Drawable]) -> void:
	for item in items:
		item.resize(2)
		print(item.draw())
var items: Array[Drawable] = [Banner.new("Sale"), Circle.new(3)]
render_all(items)
Banner 'Sale' at size 2
Circle with radius 6

クラスには親が1つあるため、拡張できるインターフェースは1つだけです。ファイルに保存されるなど、クラスが2つ目の役割を担う場合は、メインのインターフェースを拡張し、has_method()で2つ目の役割を確認します。

if item.has_method("save"):
	item.save()

各インターフェースは小さく保ちましょう。1つの役割に属するメソッドをいくつかだけ含めます。それを拡張するクラスは、必要なメソッドだけを記述します。

challenge icon

チャレンジ

簡単

インターフェースを使ってメディアプレーヤーを作成しましょう。

  • playable.gdで、Playableをインターフェースにします。つまり、play() -> Stringとduration() -> int(秒単位)という抽象メソッドを持つ抽象クラスにします。
  • SongはPlayableを継承します。play()はPlaying song: TITLE by ARTISTを返し、duration()は秒数を返します。
  • VideoはPlayableを継承します。play()はPlaying video: TITLE in RESOLUTIONpを返します(例:in 1080p)。duration()は秒数を返します。
  • Playlistが扱うのはPlayableだけです。play_all()は各アイテムのplay()を出力し、total_time()は合計時間をM:SS形式(秒は2桁。例:4:05)で返します。

SongとVideoのコンストラクターは用意されています。提供されたコードは、後に続くアイテムの数を読み取り、その後、アイテムごとに1行ずつ読み取ります。形式はsong TITLE ARTIST SECONDSまたはvideo TITLE RESOLUTION SECONDSです。コードはplay_all()を呼び出し、合計時間を出力します。song Imagine Lennon 183とvideo Trailer 1080 95の場合、次のように出力されます。

Playing song: Imagine by Lennon
Playing video: Trailer in 1080p
Total time: 4:38

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

自分で試してみよう

extends Node

func _ready():
	# 提供された入出力コード: そのままにしてください
	var count := int(OS.read_string_from_stdin())
	var playlist := Playlist.new()
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		if p[0] == "song":
			playlist.add(Song.new(p[1], p[2], int(p[3])))
		else:
			playlist.add(Video.new(p[1], int(p[2]), int(p[3])))
	playlist.play_all()
	print("Total time: " + playlist.total_time())
quiz icon腕試し

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

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

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