3

我正在使用 Progress 10.1c

我有一个包含静态和非静态方法的类。

该类是用 USE-WIDGET-POOL 定义的。在析构函数中,我说“DELETE WIDGET-POOL”。

我创建了我的类的一个实例,并调用了一个方法。该方法本身使用类的静态方法之一。因此,如果我理解正确,我现在将在其自己的未命名池中拥有我的类的实例,并为类的静态成员提供一个单独的未命名小部件池。

到目前为止,一切都很好。但是我正忙于调试并且正在对代码进行更改。我重新编译并再次运行我的测试。现在我的非静态成员工作了,但是所有静态成员都来自我的类​​的旧版本,它仍然存储在静态成员池中,它的作用域是会话。换句话说,我的析构函数中的“DELETE WIDGET-POOL”删除了类实例的池,但静态成员的池仍然存在。

我可以让它加载我的课程的新版本的唯一方法是注销我的会话,然后再次登录。这在我们的环境中是一项艰巨的任务。每次进行更改时,我都必须停止并启动我的开发环境。

我试图在会话中遍历对象列表,但找不到我要查找的内容。我很有可能从错误的对象开始,或者我缺少一些关于池和正在进行的对象的知识。

有什么方法可以让我定位那个未命名的池并删除我班级的静态“实例”,而不会每次都破坏我的会话?

4

3 回答 3

2

事实证明,只需很少的编码就可以做到。我可以使用语句 DELETE OBJECT THIS-OBJECT 来删除执行该语句的实例。所以如果它在一个静态方法中,它就是被删除的静态实例。

METHOD STATIC VOID Reload () :
    DELETE OBJECT THIS-OBJECT.
END METHOD.

所以现在当我有一个新版本的类时,我只使用 MyClass:Reload()。无需结束我的会话。

感谢Tim Kuehn为我指出了正确的方向,他建议使用静态方法删除命名的小部件池。


我创建了这个例子来演示我是如何让它工作的。下面是一个带有 3 个静态方法的简单类:

/* File : rtt/cls/demo.cls */

USING Progress.Lang.*.
ROUTINE-LEVEL ON ERROR UNDO, THROW.

CLASS rtt.cls.demo USE-WIDGET-POOL :

    METHOD STATIC CHARACTER SayHello() :
      RETURN "Good-bye".
    END METHOD.

    METHOD STATIC VOID ShowMessage() :
      MESSAGE "This is the message." VIEW-AS ALERT-BOX.
    END METHOD.

    METHOD STATIC VOID Reload() :
      DELETE OBJECT this-object.
    END METHOD.

END CLASS.

我不知道其他人的环境是如何设置的,但是在我的环境中我必须登录到我们的系统才能编译和运行程序,换句话说,我有一个活动会话。

所以我编译文件:

COMPILE VALUE(SEARCH("rtt/cls/demo.cls")) SAVE.

然后我在过程编辑器中运行以下位来测试它:

USING rtt.cls.*.

demo:ShowMessage().
MESSAGE demo:SayHello().

当我运行它时,我得到一个消息框,上面写着“这是消息。”,然后是一个消息框,上面写着“再见”。正如人们所期望的那样。

但是有一个错误,它应该说“你好”,而不是“再见”,所以我编辑了我的课程(我只展示了我正在改变的两种方法:

    METHOD STATIC CHARACTER SayHello() :
      RETURN "Hello".
    END METHOD.

    METHOD STATIC VOID ShowMessage() :
      MESSAGE "That was the message." VIEW-AS ALERT-BOX.
    END METHOD.

我保存更改,像以前一样编译它,然后再次运行测试。您希望看到什么消息?我希望看到“这就是信息”。和“再见”,和以前一样。这是合乎逻辑的,因为在我当前的会话中有一个隐藏的小部件池,并且它加载了我的类的一个实例(来自我的第一个测试)。它将继续使用此实例,直到实例或池被销毁。所以我关闭了我的开发环境,注销然后再次登录以启动一个新会话。到目前为止,一切都按预期工作。

现在我再次运行我的测试,果然,我得到了我的新版本:消息是“那是消息”和“你好”。

但是现在我被告知在“你好”这个词之后添加一个感叹号。所以我改变它:

    METHOD STATIC CHARACTER SayHello() :
      RETURN "Hello!".
    END METHOD.

我保存并编译它。当我运行测试时,显然我会得到旧版本的“你好”而不带感叹号。在我的更改生效之前,我必须再次重新启动我的会话。我真的不想再这样做了。所以我改变我的测试如下:

USING rtt.cls.*.

demo:Reload().

demo:ShowMessage().
MESSAGE demo:SayHello().

我运行它,瞧,我得到了我的最新更改。我将消息从“那是消息”更改为“它有效!”。我保存、编译并运行我的测试。我看到了什么?我看到“它有效!”。不再在编辑之间重新启动我的会话。我的解决方案非常适合我。

我尝试了各种各样的东西,但我无法让它生成错误“无法从静态成员 (15071) 引用 THIS-OBJECT 或 SUPER”。

于 2012-06-20T08:51:14.710 回答
1

静态类元素在 ABL 会话期间持续存在,“卸载”它们的唯一方法是关闭数据库连接(即关闭数据库服务器)。这将卸载所有内容,清除客户端代码,并将您留在 4GL 编辑器中。

除此之外,唯一可能的方法是为静态类创建一个命名的小部件池,然后调用(静态)方法来删除它。我不知道这是否可行。

于 2012-06-18T13:15:55.163 回答
0

“范围为类类型的静态成员。仅当创建小部件池的 ABL 会话终止时,才会隐式删除此未命名的小部件池。”

http://documentation.progress.com/output/OpenEdge102b/pdfs/dvoop/dvoop.pdf 第 5-9 页

在这种情况下会让你出事。您应该仅将静态成员用于方法或属性,它们实际上是静态的,并且在删除类的实例时不得删除或重新初始化。

当您无论如何都要使用它时,您应该使用名称定义自己的静态小部件池以及在此小部件池中创建的任何静态动态对象。那么你可以在 Reload() 中写:

METHOD STATIC VOID Reload () :
  DELETE WIDGET-POOL XYZ.
  CREATE WIDGET-POOL XYZ.
END METHOD.

另一种方法是使用单格顿类,其中定义了这个“静态”对象。然后任何时候,只要你愿意,你就可以删除这个单例的实例并创造一些新的。

于 2012-06-20T11:50:26.303 回答