封装
已知,我们可以使用 <节点>.<属性变量> 的方式引用其他节点的属性变量并修改,但这样其实很危险,例如我们可能会不小心把玩家速度设置成负数,或将玩家的生命值设置过大导致超出生命上限。
在传统编程语言中,我们通常会给变量添加对应的访问方法,下例中的 设置移动速度 方法就是一个典型:
var 移动速度: int = 100
# 假设玩家最低移动速度是 10
func 设置移动速度(新速度:int):
if 新速度 < 10:
新速度 = 10
移动速度 = 新速度
func 获取移动速度() -> int:
return 移动速度
随后,我们只要保证每次用到 移动速度 时都通过调用 设置移动速度 或 获取移动速度 方法即可。
[!note]
封装除了可以对属性值进行限制,还可以作为属性的唯一访问途径来监听属性值的变化,例如可以在
设置玩家速度方法中加一个print("玩家变速了!" + str(新速度))来提醒咱们玩家速度发生变化。
然后问题来了,肯定有一天我们会忘记 移动速度 属性还有两个对应的访问方法,这时候就需要用到 GDScript 为我们提供的 set、get 关键字来指定变量的访问方法了:
var 移动速度: int = 100: set = 设置移动速度, get = 获取移动速度
在变量初始值后面加上了一个冒号,然后写上 set = XXX, get = XXX 这样的东西,这就为移动速度属性指定了两个访问方法。
在我们需要使用 移动速度 变量时,依旧按照普通变量的方式使用即可。就是说当执行 $"玩家".移动速度 = 400 这句代码时,就会自动调用 设置移动速度 方法并将 400 作为参数传入其中,相应的,执行 print($"玩家".移动速度) 时,实际输出的就是 获取移动速度 方法的返回值。
其实上例的代码可以简化,因为 获取移动速度 这个访问方法中没有进行任何操作,只是原样返回数值而已,所以可以省略掉这个方法和对应的 get = XXX。
可运行的例子:
var 属性:int = 10:set = _设置属性, get = _获取属性
func _设置属性(新的值:int):
if 新的值 > 0:
属性 = 新的值
else:
属性 = 新的值 * 新的值
func _获取属性() -> int:
if 属性 == 0:
print("巧了,属性值竟然是零")
return 属性
func _run():
print(属性)
属性 = 0
print(属性)
属性 = -22
print(属性)
如果现在执行 _run 方法,则会看到如下输出:
10
巧了,属性值竟然是零
0
484
[!tip]
_设置属性和_获取属性方法作为属性的访问方法,咱一般不希望别人随便使用,所以起名字的时候给加上下划线前缀来告诉别人没事别用我。
简写形式
每次定义这种 设置xxx、获取xxx 的方法也很麻烦,所以 Godot 给咱提供了一种简便的方式:
var 属性 = 100:
set(新的值):
if 新的值 > 0:
属性 = 新的值
else:
属性 = 新的值 * 新的值
get:
if 属性 == 0:
print("巧了,属性值竟然是零")
return 属性
这段代码与上面可运行的例子的逻辑相同,关键语法就是把 set = XXX 这种东西改成了一个类似名为 set 方法的结构,get 同理,但要注意这里不需要 func 关键字。