内部类
本课属于 Coddy GDScript 学习旅程的“面向对象编程”单元。第 41 课,共 65 课。
一个类可以使用关键字 class、一个名称和一个缩进的主体,在类内部声明另一个类。这个内部类是属于外部类的辅助类型:
# inventory.gd
class_name Inventory
extends RefCounted
const MAX_STACK := 5
class Slot:
var item_name: String
var count: int
func _init(new_name: String, new_count: int) -> void:
item_name = new_name
count = mini(new_count, MAX_STACK)
func _to_string() -> String:
return "%s x%d" % [item_name, count]
var slots: Array[Slot] = []
func add(item_name: String, count: int) -> Slot:
var slot := Slot.new(item_name, count)
slots.append(slot)
return slot在 inventory.gd 中,内部类是 Slot。其他文件都通过外部类访问它:Inventory.Slot。
# main.gd
var bag := Inventory.new()
bag.add("Potion", 9)
var arrows: Inventory.Slot = bag.add("Arrow", 3)
print(bag.slots) # [Potion x5, Arrow x3]
var gem := Inventory.Slot.new("Gem", 1)没有 extends 的内部类会继承 RefCounted,它和其他类一样,可以有变量、构造函数和方法。它可以使用外部类的常量和枚举(上面的 MAX_STACK),但不能访问外部类的成员变量:Slot 无法访问 slots,因为槽位是一个独立的对象。将它需要的值传给它的构造函数。
如果某个小型类型只有与外部类配合使用时才有意义,例如库存中的一个槽位或分数表中的一条记录,就可以使用内部类。如果游戏的其他部分会单独使用某个类型,就应该为它单独创建一个文件,并使用 class_name。
挑战
简单构建一个 Leaderboard,其条目是一个内部类。
- 在
Leaderboard内声明内部类Entry,由其构造函数设置player_name和score,并让_to_string()返回Ada: 120。 entries是一个由Entry组成的类型化数组,顺序与玩家首次出现的顺序一致。submit(player, score)会为新玩家添加一个条目。对于已有条目的玩家,保留两个分数中较高的那个。best()返回分数最高的条目。如果分数相同,则保留先出现的条目。
提供的代码会读取后续分数的数量(Ada 120),提交这些分数,然后打印每个条目和最佳条目(至少会提供一个分数)。对于 Ada 120、Bo 90、Ada 80、Bo 150、Cy 150,输出为:
Ada: 120
Bo: 150
Cy: 150
Best: Bo: 150你的代码写在 leaderboard.gd 中。main.gd 包含提供的输入/输出代码,不能编辑。
亲手试试
extends Node
func _ready():
# 已提供的输入/输出代码:保持原样
var board := Leaderboard.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
board.submit(parts[0], int(parts[1]))
for entry in board.entries:
print(entry)
print("Best: ", board.best())
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: GDScript 在线编译器