马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?站点注册
×
PowerBuilder 变量作用域:全局/实例/共享/局部到底差在哪
很多从别的语言转到 PowerBuilder 的人,第一次写代码就踩在同一个坑上:在窗口里声明了一个变量,切到另一个窗口想用却"找不到";或者明明改了某个值,刷新界面却没变。根子都在"变量作用域"——PowerBuilder 把变量分成全局(Global)、实例(Instance)、共享(Shared)、局部(Local)四种,它们活在哪、谁能看见、什么时候被销毁,规则和其它语言不太一样。本文只讲清这一件事。
一、四种作用域分别"住"在哪
- 全局变量(Global):写在独立的 Global Variables 声明区(或 .srs 里的 global variables 段),整个应用任何对象、任何脚本都能直接引用。它跟着应用进程活,应用不关就一直在。
- 实例变量(Instance):写在某个对象(窗口、用户对象、自定义类 n_*)的 Instance Variables 区。每个对象实例各持一份,窗口打开两个就各有一份,互不影响。
- 共享变量(Shared):同样写在对象里,但同一个类/窗口的所有实例共享同一份。不管你 open 了这个窗口几次,shared 变量只有一份,所有实例读写的是同一个。
- 局部变量(Local):写在某个事件/函数脚本内部,用 integer li_x 这种。只在那段脚本执行期间存在,脚本一跑完就销毁。
一句话记忆:全局=全应用一份;实例=每个对象一份;共享=每类对象一份;局部=每次调用一份。
二、最容易翻车的三个误用
1. 局部变量"遮蔽"实例变量
如果你在窗口的 Instance Variables 里写了 string gs_user,又在某个按钮的 clicked 事件里写了 string gs_user,那么事件里的 gs_user 是新建的局部变量,改它不会动到实例那份。结果:你以为改了用户名,其实窗口别处读到的还是旧值。规避:实例变量加统一前缀(很多团队用 iv_),局部变量用 li_/ls_,一眼能区分。
2. 误把"应该共享"的状态写成实例变量
比如你想统计"这个窗口被打开过几次"。如果在 Instance Variables 写 integer ii_count 并在 open 里 ii_count++,那每 open 一个窗口实例,计数都从 0 开始——永远统计不到总数。正确做法是用 Shared Variables:shared integer si_count,所有实例 +1 都落在同一份上。
3. 全局变量满天飞
图省事把所有状态都声明成全局变量,短期内"哪都能用",长期就是噩梦:命名冲突、无法测试、多线程下互相踩。PB 12.5 之后更推荐把状态收敛到 nvo(非可视化对象)的实例变量里,再用全局单例去取,而不是裸写 global。
三、实例参考(动手步骤)
下面用用户对象的最小例子,验证"共享 vs 实例"的差异。
- // 在 u_counter 用户对象的 Instance Variables 区:
- integer ii_mine
- shared integer si_common
- // 在 u_counter 的某个函数 of_bump() 里:
- ii_mine ++
- si_common ++
- return "instance=" + string(ii_mine) + ", shared=" + string(si_common)
复制代码- // 窗口 open 事件:创建两个实例
- iu_a = create u_counter
- iu_b = create u_counter
- // 分别调用
- // iu_a.of_bump() -> instance=1, shared=1
- // iu_a.of_bump() -> instance=2, shared=2
- // iu_b.of_bump() -> instance=1, shared=3 // 注意:iu_b 的 instance 从 1 重新开始,shared 继续累加
复制代码
关键点:iu_b 的 ii_mine 重新从 1 计,因为它属于另一个实例;而 si_common 是 3,因为两份实例共享同一份 shared。这正是"统计总次数"要用 shared 的原因。
四、实操检查清单
- 状态只在一个窗口/对象内用时,优先用实例变量,别写全局。
- 需要"所有实例共享同一份"(计数器、配置开关、连接句柄)时,用 Shared Variables。
- 实例变量加 iv_ 前缀、局部变量加 li_/ls_,避免局部遮蔽实例导致"改了不生效"。
- 临时计算、循环变量一律用局部变量,脚本结束即释放,不占对象内存。
- 能用对象封装的状态,就不要裸写 Global Variables;全局越少,后期越好维护、越好测。
- 多线程/异步场景(uo_thread)下,避免直接读写共享/全局变量,必要时加简单锁或改为消息传递。
变量作用域不是语法细节,它直接决定了你的状态"到底属于谁、改了谁看得到"。把上面几条规则落到命名习惯上,PB 里绝大多数"莫名其妙不生效"的 bug 都会消失。 |