Menu
CoddyTech

继承链

本课属于 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_speed

RaceCar 拥有 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, Plane
Parse Error: Expected end of statement after superclass, found "," instead.

GDScript 不支持多重继承。当一个类需要两个类的功能时,可以把它们放在同一条继承链上,也可以给它一个另一个类的对象供它使用(后面的章会介绍这一点)。

challenge icon

挑战

简单

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())
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: GDScript 在线编译器