继承链
本课属于 Coddy GDScript 学习旅程的“面向对象编程”单元。第 18 课,共 65 课。
子类本身也可以是父类。每个 extends 都会为继承链增加一级:
# 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_speedRaceCar 拥有 Car 和 Vehicle 的所有内容。每个 super() 都会上升一级,因此一次调用会运行 describe() 的全部三个版本:
print(RaceCar.new(300).describe())Car with 4 wheels, top speed 300调用方法或读取变量时,Godot 会先在对象自身的类中查找,然后在其父类中查找,再在父类的父类中查找,并使用找到的第一个结果。RaceCar.new(300).wheels 是在上两级的 Vehicle 中找到的。
每个类都恰好有一个父类。extends 只能接受一个类,列出两个会导致解析错误:
class_name FlyingCar
extends Car, PlaneParse Error: Expected end of statement after superclass, found "," instead.GDScript 不支持多重继承。当一个类需要两个类的功能时,可以把它们放在同一条继承链上,也可以给它一个另一个类的对象供它使用(后面的章会介绍这一点)。
挑战
简单character.gd 中包含已完成的 Character 类:包含名称、hp、返回 NAME (HP HP) 的 describe(),以及返回 1 的 attack()。在此基础上再构建两层:
Warrior继承Character,并添加strength。它的构造函数将名称和 hp 传给super()。describe()会在父类的文本后添加, strength S,而attack()返回 strength。Knight继承Warrior,并添加armor。它的构造函数将名称、hp 和 strength 传给super()。describe()会在Warrior的文本后添加, armor A,而attack()返回Warrior的攻击值加上5。
提供的代码会读取后续角色的数量,然后为每个角色读取一行:character NAME HP、warrior NAME HP STRENGTH 或 knight NAME HP STRENGTH ARMOR。代码会输出 describe() 的结果和攻击值。对于 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())
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: GDScript 在线编译器