Menu
CoddyTech

内部类

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

challenge icon

挑战

简单

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

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

面向对象编程中的所有课

自己练习: GDScript 在线编译器