インターフェース設計
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 *= factorCircle も 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つの役割に属するメソッドをいくつかだけ含めます。それを拡張するクラスは、必要なメソッドだけを記述します。
チャレンジ
簡単インターフェースを使ってメディアプレーヤーを作成しましょう。
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())
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: GDScriptオンラインコンパイラ