网页
资讯
视频
图片
知道
文库
贴吧
地图
采购
进入贴吧
全吧搜索
吧内搜索
搜贴
搜人
进吧
搜标签
日
一
二
三
四
五
六
签到排名:今日本吧第
个签到,
本吧因你更精彩,明天继续来努力!
本吧签到人数:0
一键签到
成为超级会员,使用一键签到
一键签到
本月漏签
0
次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行
补签
。
连续签到:
天 累计签到:
天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
01月01日
漏签
0
天
godot吧
关注:
9,750
贴子:
43,034
看贴
图片
吧主推荐
游戏
1
2
下一页
尾页
38
回复贴,共
2
页
,跳到
页
确定
<<返回godot吧
>0< 加载中...
GDScript小技巧——只读属性
只看楼主
收藏
回复
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
在进行类属性的封装时,我们希望将某些属性设置为外部只读状态
而GDScript不支持像 C井 那样使用readonly关键字或使用{ get; private set; } 这样的访问器
但是GDScript也提供了getter和setter访问器,于是,就有了以下实现方法
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
这里定义了两个变量,member供外部访问,使用getter访问器,_member供内部访问
GDScript不具有 C井 那样有访问级别的特性,所有成员都是公开的(public),而即使在命名时加上下划线也不会变成私有的(private)
不过官方是说法是“在用户必须覆盖的虚方法、私有函数、私有变量的名称前加一个下划线(_)”
实际上只是命名规范,并没有真正实现私有就是了(划掉)
2026-01-01 02:45:41
广告
不感兴趣
开通SVIP免广告
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
这样当外部访问member变量时,实际上是在访问_member变量,这也就导致,即使将member的值设置为true,再次访问时,它的值还是false
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
虽然说外部也能直接修改_member的值就是了(划掉)
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
接下来是更严格的访问限制
这里使用了assert关键字,在外部设置member值时,会直接触发断言,而暂停项目
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
至于为什么使用assert,而不是push_error,和print,因为assert是最醒目的错误输出
神秘海马人
GDScript
5
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
感谢分享
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
而对于字典(Dictionary)和数组(Array)这样的集合,有专门的方法来实现只读
这里定义了一个member字典,并在类的构造函数中将其设置为只读
而这会使member这个字典达成同2楼一样的效果,无论设置的键值对是多少,返回的始终是定义的常量{"key":10},
Array也是一样的写法
但是这样会变成内部和外部都是只读的
2026-01-01 02:39:41
广告
不感兴趣
开通SVIP免广告
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
所以,我们可以套用之前的方法,使这个属性仅外部只读,在这里,实现了和make_read_only方法一样的效果,增加了设置值时断言的效果
这样访问值时获取的是"key":1,而不是"key":10,并且还能够通过修改_member变量来更改访问member变量时获取的值,而不是像make_read_only方法那样完全写死
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
GDScript与 C井 不同的是在getter访问器访问该属性自身时,不会导致getter被无限次递归调用(但是在匿名的getter/setter调用具名的getter/setter时,就会导致无限递归)
所以,在这里,如果删去_member变量,这样也就实现了真正的只读,member属性始终是11,是只读的。(那我还不如定义一个常量(划掉))
五条牢师还在尽力
动画特效
4
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
挺好的,也可以复写godot object的get method,省去getter这一步
某131
GDScript
5
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
纠正一下8-9楼的小错误
利用setter和getter实现的只读和make_read_only的效果是不一样的哦
make_read_only会使数组/字典对象内的内容无法进行修改,但变量本身是可以重新赋值的
举个例子,一个object对象中分别定义了array和dictionary两个变量,并对这两个字典/数组进行make_read_only后:
object.array[2] = "hello" //不可行。
object.array= ["hello", "world"] //可行。
object.dictionary["hello"] = "world" //不可行。
object.dictionary= {"hello": "world"} //可行。
前面楼主说的测试的时候make_read_only没用,可能也是因为楼主并不是尝试对字典/数组的内容进行修改,而是直接对变量进行赋值
某131
GDScript
5
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
而同样的情况下,利用楼主的setter/getter实现字典/数组变量的只读后的结果:
object.array[2] = "hello" //可行。
object.array= ["hello", "world"] //不可行。
object.dictionary["hello"] = "world" //可行。
object.array= {"hello": "world"} //不可行。
这是因为字典/数组本身并没有调用make_read_only方法,因而它们的内容是可以被修改的。我们通过object.array(get)(dictionary同理)获得了字典/数组的引用,而在这期间我们并没有对字典/数组变量通过赋值(或者别的手段)进行更改,因此不会触发变量的set方法。获取字典/数组的引用后,我们通过调用方法/下标赋值等等对字典/数组内容的修改是可以正常生效的。
而直接对array和dictionary变量进行赋值是不可行的,这一点就是楼主在前面的setter和getter起到的作用
某131
GDScript
5
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
如果想要实现字典/数组及其内容都使外部只读,我们可以采用这种写法:
var array: Array:
get:
return _array.duplicate()
这样在对array进行访问时,返回的是_array的副本,接下来不论怎样进行操作都不会影响到_array本身的内容了。
字典同理。
不过这么搞可能会比较占性能(我猜的)
2026-01-01 02:33:41
广告
不感兴趣
开通SVIP免广告
fang_chu
数学算法
7
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
综合一下12-14楼的说法,对集合的只读其实这样实现就行,这里引用我开源项目的代码
对集合写上getter,然后再在构造函数里make_read_only就行
这样修改引用会失效,修改元素会抛出异常
登录百度账号
扫二维码下载贴吧客户端
下载贴吧APP
看高清直播、视频!
贴吧页面意见反馈
违规贴吧举报反馈通道
贴吧违规信息处理公示