封装
已知,我们可以使用 <节点>.<属性变量>
的方式引用其他节点的属性变量并修改,但这样其实很危险,例如我们可能会不小心把玩家速度设置成负数,或将玩家的生命值设置过大导致超出生命上限。
在传统编程语言中,我们通常会给变量添加对应的访问方法,下例中的 设置移动速度
方法就是一个典型:
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
关键字。