Menu
CoddyTech

只读属性

本课属于 Coddy GDScript 学习旅程的“面向对象编程”单元。第 29 课,共 65 课。

有些值应该可以从外部读取,但不能被赋值:例如在对象创建时只设置一次的 ID,或者根据其他数据计算出的值,例如面积或总数。具有 get 块且没有 set 块的属性可以实现这一点:

# ticket.gd
class_name Ticket
extends RefCounted

var _number: int
var number: int:
	get:
		return _number

func _init(start_number: int) -> void:
	_number = start_number

构造函数会将值存储在私有的 _number 中,而公共的 number 只会返回这个值。从外部给 number 赋值不会报错,但也不会改变任何内容,因为 getter 会一直返回 _number:

var ticket := Ticket.new(42)
ticket.number = 7
print(ticket.number) # 42

计算属性本身没有值:每次读取时,它的 getter 都会计算出值,因此它始终与其来源数据保持一致:

# room.gd
class_name Room
extends RefCounted

var width: int = 4
var length: int = 5
var area: int:
	get:
		return width * length
var room := Room.new()
print(room.area) # 20
room.width = 6
print(room.area) # 30

普通的 var area 每次在 width 或 length 发生变化时都必须手动更新,忘记更新一次就会导致它出错。计算得出的 area 不会过时,也没人能给它赋一个错误的值。

如果某个值对每个对象都相同且永远不会改变,就在类中使用常量:const MAX_GUESTS = 4。在程序运行前就会报告对常量赋值的情况。

challenge icon

挑战

简单

Order 类在 order.gd 中将 ID 存储在 _id 中,并将每个订单项的总价(价格乘以数量)存储在 _line_totals 中。使用 get 块将它的四个公共属性设为只读:

  • order_id 返回 _id。
  • subtotal 返回 _line_totals 中各项的总和。
  • 当小计大于或等于 50 时,shipping 返回 0;否则返回 5。
  • total 返回小计加运费。

提供的代码会读取订单 ID、商品数量,然后为每件商品读取一行 price quantity。每读取一件商品后,它都会输出小计、运费和总价。最后,它会尝试将四个属性都设为 0,然后输出 ID 和总价,这两者都必须保持不变。对于 ID 为 7,商品分别为 12 2 和 30 1 的情况,输出如下:

Subtotal 24, shipping 5, total 29
Subtotal 54, shipping 0, total 54
Order #7: 54

你的代码写在 order.gd 中。main.gd 包含提供的输入/输出代码,不能修改。

亲手试试

extends Node

func _ready():
	# 提供的输入输出代码:保持原样
	var order := Order.new(int(OS.read_string_from_stdin()))
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		order.add_item(int(parts[0]), int(parts[1]))
		print("Subtotal %d, shipping %d, total %d" % [order.subtotal, order.shipping, order.total])
	# 尝试覆盖只读属性的代码
	order.order_id = 0
	order.subtotal = 0
	order.shipping = 0
	order.total = 0
	print("Order #%d: %d" % [order.order_id, order.total])
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: GDScript 在线编译器