سؤال

I'm working with Progress 10.1c

I have a class that contains both static and non-static methods.

The class is defined with USE-WIDGET-POOL. In the destructor I say "DELETE WIDGET-POOL".

I create an instance of my class, and call a method. The method itself uses one of the static methods of the class. So if I understand it correctly, I will now have the instance of my class in its own unnamed pool, and a separate unnamed widget pool for the static members of the class.

So far so good. But I'm busy debugging and I'm making changes to the code. I recompile and run my test again. Now my non-static members work, but all the static members come from the older version of my class, that is still stored in the pool for static members, which is scoped to the session. In other words, the "DELETE WIDGET-POOL" in my destructor deleted the pool for the instance of the class, but the pool for the static members is still there.

The only way I can get it to load the new version of my class is to log off my session, and log on again. This is quite a mission in our environment. Every time I make a change, I have to stop and start my development environment.

I tried to walk the list of objects in my session, but could not find what I'm looking for. There's a good chance I'm starting at the wrong object, or I'm missing some knowledge of pools and objects in Progress.

Is there any way for me to target that unnamed pool and delete the static "instance" of my class, without destroying my session every time?

هل كانت مفيدة؟

المحلول 2

This turned out to be doable with very little coding. I can use the statement DELETE OBJECT THIS-OBJECT to delete the instance executing that statement. So if it's in a static method, it is the static instance that gets deleted.

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

So now when I have a new version of the class, I just use MyClass:Reload(). No need to end my session.

Thanks to Tim Kuehn for pointing me in the right direction with his suggestion of using a static method to delete the named widget-pool.


I have created this example to demonstrate how I got it to work. Below is a simple class with 3 static methods:

/* 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.

I don't know how other people's environments are set up, but in my environment I have to log on to our system to be able to compile and run programs, in other words, I have an active session.

So I compile the file:

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

And then I run the following bit in Procedure Editor to test it:

USING rtt.cls.*.

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

When I run this, I get a message box that says "This is the message.", followed by a message box that says "Good-bye". Exactly as one would expect.

But there's a bug, it's supposed to say "Hello", not "Good-Bye", so I edit my class (I'm only showing the two methods I'm changing:

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

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

I save my changes, compile it as before, and I run the test again. What messages do you expect to see? I expect to see "This is the message." and "Good-bye", same as before. That's logical, because there is a hidden widget-pool in my current session, and it has an instance of my class loaded (from my first test). It will keep on using this instance until the instance or the pool is destroyed. So I shut down my development environment, log off and then log on again to start up a new session. So far everything is working exactly as expected.

Now I run my test again, and sure enough, I get my new version: the messages are "That was the message" and "Hello".

But now I'm told to add an exclamation after the word "Hello". so I change it:

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

I save it and compile it. When I run the test, obviously I will get the older version that says "Hello" without the exclamation. I have to restart my session again before my changes become active. I really don't want to do that again. So I change my test as follows:

USING rtt.cls.*.

demo:Reload().

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

I run it and voilà, I get my latest changes. I change the message from "That was the message" to "It works!". I save, compile and run my test. What do I see? I see "It works!". No more restarting my session between edits. My solution works perfectly for me.

I tried all sorts of stuff, but I cannot get it to generate the error "Cannot Reference THIS-OBJECT or SUPER from a static member (15071)".

نصائح أخرى

Static class elements last for the duration of the ABL session, and the only way to 'unload' them is to have a database connection go down (ie, the db server is shut down). This unloads everything, clears the client code, and leaves you in the 4GL editor.

Beyond that, the only other possible way is to create a named widget pool for the static class, then call a (static) method to delete that. I have no idea if this would work or not.

"Static members that are scoped to the class type. This unnamed widget pool is implicitly deleted only when the ABL session in which the widget pool is created terminates."

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

In this case make you something wrong. You should use the static members only for methods or properties, which are realy static and must be not deleted or reinitialised when is deleted the instance of class.

when you will use it anyway, you should define your own static widget-pool with name and any static dynamic objects create in this widget-pool. then can you in Reload() write:

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

other way is to use a singelton class, where are defined this 'static' objects. then anytime, when you will, you can delete the instance of this singelton and make some new fresh.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top