接口设计
本课属于 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一个类只有一个父类,因此只能扩展一个接口。当一个类还要担任第二种角色(例如保存到文件)时,扩展主要接口,并使用 has_method() 检查它是否具备第二种角色:
if item.has_method("save"):
item.save()让每个接口都保持精简:只包含几个属于同一角色的方法。扩展该接口的类只需编写自己需要的方法。
挑战
简单围绕一个接口构建媒体播放器。
- 在
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格式返回(秒数占两位,例如4:05)。
Song 和 Video 的构造函数已经写好。提供的代码会读取后续项目的数量,然后每个项目读取一行: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 在线编译器