在PowerBuilder5.0 的PowerScript 语 言 中, 对 于 函 数 和 事 件 的 处 理 有 了 新 的 拓 展。 记 得 我 们 曾 在 关 于PowerBuilder 的 面 向 对 象 特 性 中 介 绍 过,PowerBuilder 的 对 象 由3 部 分 内 容 组 成: 属 性、 函 数 和 事 件。 而 在5.0 中, 对 于 这 部 分 理 论 进 行 了 调 整: 将 函 数 和 事 件 进 行 了 同 化, 统 称 为 方 法(Method )。 在Script 中 调 用 函 数 和 调 用 事 件 的 方 法 进 一 步 接 近, 事 件 也 可 带 有 参 数, 并 具 有 返 回 值。
函 数 和 事 件
即 统 称 方 法 调 用 的 语 法 为:
{ objectname.} { type } { calltype } { when }
functionname ( { argumentlist } )
这 些 参 数 的 说 明 如 下:
type 所调用方法的类型 可以是EVENT或FUNCTION,其中FUNCTION为缺省。 calltype 所调用的类型 可以是动态(关键词为DYNAMIC)或静态 (关键词为STATIC),其中STATIC为缺省。 when 调用的时间 POST或TRIGGER,其中TRIGGER为缺省。
当 然, 并 不
是 所 有 的 选 项 都 是 有 意 义 的。 比 如 我 们 不 会 去 调 用 一
个 动 态 的PowerScript 对 象 函 数。 只 有 在 用 户 自 定 义 函 数
中, 我 们 才 可 能 动 态 地 调 用 一 个 函 数。
允 许 对 函 数 的 调 用 采 用Post 方 式
是5.0 的 新 特 点。 当 函 数 以 这 一 方 式 被 调 用 时, 系 统 将
这 一 函 数 放 在 了 这 个 对 象 的 消 息 队 列 的 末 尾, 当 前 面
的 所 有 消 息 都 被 执 行 了 以 后, 这 一 函 数 才 被 调 用。 采
用 这 种 方 式 调 用 函 数, 您 仍 可 以 传 递 参 数, 但 是 却 无
法 得 到 返 回 值。 如:
// 合 法 语 句 POST wf_calculate(x,y) // 非 法 语 句 Statue = Woo.cb_1.POST EVENT Clicked()
关 键 词STATIC 是
表 示 您 现 在 所 调 用 的 方 法 和 您 所 使 用 的 参 数 在 编 译
时 是 存 在 的。 如:
STATIC EVENT ue_validates(ls_name, li_id)
如 果 关 键 词DYNAMIC 出 现 在 这 一 行 调 用 的 函 数 中,PowerBuilder 在 编 译 这 一 行 代 码 时 将 不 检 查 这 个 方 法 和 所 用 参 数 的 有 效 性, 只 是 到 了 运 行 时, 系 统 才 会 到PBD 的 库 中 去 搜 索 这 个 方 法。
当 我 们 在 运
行 时 需 要 根 据 当 前 不 同 情 况 的 上 下 文 调 用 不 同 的 对
象 函 数 时, 我 们 会 用 到 这 一 关 键 词。 例 如:
PowerObject lpo lpo = dw_1 lpo.dynamic show()
在 运 行 前, 也 许 我 们 还 无 法 了 解 到 我 们 要 对 哪 个 对 象 进 行show() 的 操 作, 只 能 等 到 运 行 时 才 能 确 定 操 作 对 象。 如 果 在 上 述 的 语 句 中 我 们 去 掉 关 键 词dynamic, 系 统 编 译 将 出 现 错 误, 因 为PowerObject 对 象 类 并 没 有show 这 个 对 象 函 数。 一 般 来 说,Dynamic 关 键 词 只 有 在 调 用 多 态 方 法 时 才 可 能 用 到, 这 实 际 上 也 是 进 一 步 拓 展 了PowerBuilder 的 面 向 对 象 的 特 性。
不 过 我 们 在 调 用 方 法 时 使 用STATIC 这 一 关 键 词, 一 般 也 只 是 为 了 系 统 在 编 译 时 对 您 所 引 用 的 方 法 进 行 一 下 语 法 检 查, 以 确 保 引 用 的 正 确 性。 如 果 我 们 在 运 行 时 改 变 了 方 法 的 对 象 名 称, 系 统 将 调 用 改 变 后 的 对 象 的 方 法。
我 们 来 作 这
样 一 个 实 验:
在 窗 口 中 我 们 声 明 一 个 实 例 变
量:
CommandButton icb
在 窗 口 中 有 两 个 按 钮, 在 第 一
个 按 钮cb_1 的constructor 事 件 中 键 入:
icb = this
clicked 事 件 中 键 入:
icb.resize(200,100)
窗 口 的 第 二 个 按 钮cb_2 的clicked 事
件 中 编 码 如 下:
icb = this
当 这 个 窗 口 运 行 时, 在cb_2 的 构 造 事 件 中 变 量icb 引 用 定 为cb_1, 如 果 这 时 我 们 首 先 点 击 第 一 个 按 钮, 这 个 按 钮 的clicked 事 件 被 触 发, 调 用icb.resize() 函 数, 这 个 按 钮 的 尺 寸 将 随 之 改 变。 我 们 点 击 一 下cb_2 后, 再 按 动 第 一 个 按 钮, 这 时 您 会 发 现,cb_2 的 尺 寸 也 改 变 了。 因 为 在 我 们 按 下 第 二 个 按 钮 后icb 的 引 用 赋 值 已 经 改 变 为 了cb_2。
在PowerBuilder5.0 所 包 括 的Anchor Bay Nut Company sample application 这 一 实 例 中 就 使 用 了 一 个 动 态 调 用 函 数 的 实 例。m_datareview_framemenu 是 一 个 祖 先 菜 单 类, 它 的 后 继 菜 单 类 有m_datareview_custsheet,m_datareview_ordsheet 等, 分 别 为w_datareview_custsheet,w_datareview_ordsheet 等 窗 口 所 拥 有, 这 些 窗 口 是MDI 下 的 不 同 表 单, 对 这 些 表 现 不 同 信 息 的 表 单 进 行 输 出(export) 操 作 是 各 不 相 同 的, 因 此 各 自 的 窗 口 分 别 有 不 同 的 多 态 函 数wf_export 处 理 各 自 的 输 出 操 作。 可 是 在 对m_datareview_framemenu 菜 单 的m_export 项 编 码 时, 我 们 无 法 知 道 当 前 激 活 的 表 单 是 哪 一 个, 所 以 我 们 只 能 动 态 地 调 用 这 个 窗 口 函 数:
guo_global_vars.ish_currentsheet.DYNAMIC wf_export()
其 中guo_global_vars.ish_currentsheet
的 值 是 当 前 活 动 表 单 的 引 用, 而 这 个 值 在 声 明 时 却 只
能 声 明 作 这 些 表 单 共 同 的 祖 先 类w_datareview_frame 的 引 用,
因 为 这 个 祖 先 窗 口 是 没 有wf_export 这 个 窗 口 函 数 的, 所
以 我 们 必 须 使 用DYNAMIC 这 个 关 键 词。 这 个 例 子 在abnc_rev.pbl
库 中 可 以 找 到, 有 兴 趣 的 人 员 可 以 好 好 理 解 一 下。 如
果PowerBuilder 没 有 这 个 调 用 动 态 函 数 的 功 能, 那 么 我 们 只
能 采 用 其 它 方 法 替 代 解 决, 如:
1. 在 祖 先 窗 口w_datareview_frame 中 定 义
一 个 空 白 的wf_export() 函 数;
2. 使 用SWITCH CASE 语 句 来 决 定 调 用 哪
个 窗 口 函 数。
显 然 第 二 种 方 法 不 是 一 个 好 的
面 向 对 象 的 程 序 设 计。
在 目 前 为
止, 函 数 和 事 件 仍 存 在 着 一 些 差 异, 它 们 表 现 在 事 件
只 与 对 象 有 关, 而 函 数 既 包 括 对 象 函 数, 也 有 一 部 分
是 全 局 的。
在PowerBuilder 中, 事 件 和 函 数 的 搜
索 顺 序 是 不 同 的。
在 运 行 时, 用 户 调 用 了 一 个 未
定 义 的 事 件, 系 统 将 不 会 产 生 任 何 错 误, 但 是 调 用 了
未 定 义 函 数, 系 统 将 触 发 错 误。
函 数 可 以 重 载, 而 事 件 不 能。
对 自 定 义 的 函 数, 您 可 以 指 定
其 访 问 范 围 如public,private,protect 等, 但 是 事 件 不 能, 其
访 问 范 围 全 部 为public。
您 可 以 很 容 易 地 在 继 承 对 象 中 扩 展 或 覆 盖 祖 先 对 象 事 件 中 的 代 码, 但 是 如 您 将 在 后 继 对 象 中 对 函 数 进 行 覆 盖 就 很 困 难 了, 您 必 须 要 重 新 定 义 这 个 函 数。
限 于 篇 幅,
我 们 只 能 对 第 二 条 进 一 步 引 申 说 明:
由 于 函 数 是 支 持 重 载 的, 当 您
的 代 码 调 用 一 个 函 数 时, 系 统 将 本 着 兼 容 匹 配 的 原
则, 搜 索 您 将 要 调 用 的 函 数, 因 此 当 您 调 用 重 载 函 数
时, 一 定 要 指 明 参 数 的 类 型。 例 如 数 据 窗 口 表 达 式 的
返 回 值 是ANY 型 的, 您 应 当 这 样 明 确 指 出:
wf_process_search(string(dw_1.object.name[3]))
而 不 要 笼 统 写 成:
wf_process_search(dw_1.object.name[3])
而 另 一 方 面,PowerBuilder 的 事 件 是 不 支 持 重 载 的, 但 是 后 继 对 象 的 事 件 却 可 以 扩 展 祖 先 对 象 的 同 一 事 件 的。 系 统 搜 索 到 您 将 要 调 用 的 对 象 事 件 后, 还 要 继 续 上 溯 寻 找 它 的 祖 先, 直 到 祖 先 事 件 的 代 码 为 空 或 被 覆 盖 了 为 止, 并 要 首 先 执 行 其 祖 先 代 码。
究 竟 是 在 函 数 中 还 是 在 事 件 里 编 写 您 的 应 用 中 的 复 杂 的 商 业 逻 辑, 这 只 是 一 个 编 程 风 格 问 题, 一 般 对 系 统 的 运 行 效 率 将 不 产 生 任 何 影 响。
此 外 另 一 点
要 说 明 的 是 以 上 所 谈 到 的 在5.0 中 新 增 加 的 语 法 功 能 是4.0
以 下 版 本 的 超 集, 也 就 是 说, 这 种 方 法 兼 容 了 以 往 调
用 函 数 和 触 发 事 件 的 语 法, 以 保 证PowerBuilder 新 版 本 的 向
上 兼 容 性。PowerBuilder5.0 中 仍 然 支 持 以 往 的TriggerEvent() 函 数、PostEvent()
函 数 和 关 键 词CALL 语 句。 只 是 以 前 的 触 发 事 件 的 方 法 无
法 在 其 中 加 入 参 数。