Cloning an object

Posted by Tim Kuehn on 30-Aug-2012 13:27

I was looking at cloning an object to another instance with the same values, and was going to over-ride Progress.Lang.Clone() like it says to do in the manual.

The issue is, based on what I've seen sof ar, the Clone() method has to return Progress.Lang.Object instead of the originating class's data type, which means I'd have to CAST() the result for every caller, which is a needless pain in the butt.

Is there a way to override Progress.Lang.Object:Clone() using a different return type, or am I stuck?

All Replies

Posted by Peter Judge on 30-Aug-2012 13:37

timk519 wrote:

I was looking at cloning an object to another instance with the same values, and was going to over-ride Progress.Lang.Clone() like it says to do in the manual.

The issue is, based on what I've seen sof ar, the Clone() method has to return Progress.Lang.Object instead of the originating class's data type, which means I'd have to CAST() the result for every caller, which is a needless pain in the butt.

Is there a way to override Progress.Lang.Object:Clone() using a different return type, or am I stuck?

There is no way to override purely based on the return value for a method (in OOABL and also other langs).

How frequently do you plan on calling Clone()?   And how many types do you want to clone?

You could take the Fechner Approach and create yourself a wee include that does the casting based on an argument

{clone.i

     cast(&1:Clone(), "&2")

}

oNewObj = {clone.i objSourceRef Tims.Type}.

You could add a static method to the type that did the casting for you.

class Tims.Type:

   method public static Tims.Type Clone(input objSource as Tims.Type):

      return cast(objSource:Clone(),Tims.Type).

   end.

-- peter

Posted by Admin on 30-Aug-2012 13:37

Is there a way to override Progress.Lang.Object:Clone() using a different return type, or am I stuck?

No - there is no method polymorphism based on the return type only.

If your method should return an Apple, make a CloneApple() method.

Posted by Admin on 30-Aug-2012 13:42

You could take the Fechner Approach and create yourself a wee include that does the casting based on an argument

May I patent that? I've heard that's a good revenue stream these days

Posted by Peter Judge on 30-Aug-2012 13:47

That makes 3 now ...

-- peter

Posted by Admin on 30-Aug-2012 14:02

You could take the Fechner Approach and create yourself a wee include that does the casting based on an argument

Hi Peter, after reviewing your entry once more, I must admit it does not exactly quality for a "Fechner OO simplifying" include file...

I usually do include files only when I need the same argument (typically a class name) twice and one of them as a quoted string. In those cases using the Include file parameters avoids typos that would only be checked at runtime as it's validated now in the CAST method.

Consultingwerk/new-array.i

CAST (System.Array:CreateInstance (Progress.Util.TypeHelper:GetType("":U), ), "[]":U)

DEFINE VARIABLE oButtons AS "System.Windows.Forms.Buttons[]" NO-UNDO.

oButtons = {Consultingwerk/new-array.i System.Windows.Forms.Buttons 5}.

Certainly less likely to error as

oButtons = CAST (System.Array:CreateInstance (Progress.Util.TypeHelper:GetType("System.Windows.Forms.Button":U), 5), "System.Windows.Forms.Button[]":U). /* note the first use of the type-name would only be validated at runtime */

Or Consultingwerk/parse-enum.i

CAST (System.Enum:Parse (Progress.Util.TypeHelper:GetType("":U), ), "":U)

Posted by Tim Kuehn on 30-Aug-2012 14:11

Thanks for your answers - that's what I was afraid of.

I'll go with the ObjectName:CloneObjectName() approach.

It does raise the question, namely why bother having a Clone() method in progress.lang.class at all?

Posted by Admin on 30-Aug-2012 14:17

It does raise the question, namely why bother having a Clone() method in progress.lang.class at all?

Casting isn't that bad. Sometimes.

Posted by Tim Kuehn on 30-Aug-2012 14:23

I can certainy understand that there are places that CASTing is useful and/or necessary. IMPO, making a copy of an existing object isn't one of them though...

Posted by gamerome on 20-Jun-2013 02:35

Hello,

I've tried to use this code but it doesn't work with me... Progress crash.

You could take the Fechner Approach and create yourself a wee include that does the casting based on an argument

{clone.i 
     cast(&1:Clone(), "&2")
}

oNewObj = {clone.i objSourceRef Tims.Type}.



You could add a static method to the type that did the casting for you.



class Tims.Type:
   method public static Tims.Type Clone(input objSource as Tims.Type):
      return cast(objSource:Clone(),Tims.Type).
   end.

I've got a class inherited of Progress.Windows.Form.

I would like to clone an instance of this.

Can you help me to do this?

CLASS CustUI INHERITS Progress.Windows.Form:

/*List of all my UI components*/

END CLASS.

DEF VAR objInstance            AS CustUI NO-UNDO.

DEF VAR objInstance_cloned AS CustUI NO-UNDO.

objInstance = NEW CustUI().

/* (...) */

objInstance_cloned = objInstance:Clone().               /* ====>   Not Working  *@*#@*_!*#    */

Posted by Admin on 20-Jun-2013 02:53

>          /* ====>   Not Working  @#@_!#    */

Means what exactly?

The Clone() method if implemented by that specific type returns a Progress.Lang.Object. So you need to make sure that the class implementes the Clone() method and you need to CAST the return value to the type.

Posted by gamerome on 20-Jun-2013 03:32

Means that I'm angry!

I've tried to implemented Clone method but I don't know what sould be the code.

CLASS CustUI INHERITS Progress.Windows.Form:

    DEF VAR txtCustID   AS UltraTextEditor NO-UNDO.
    DEF VAR txtCustName AS UltraTextEditor NO-UNDO.

    METHOD PUBLIC OVERRIDE Progress.Lang.Object Clone():

       /* Not sure of the code below*/
       DEF VAR newObj AS CustUI NO-UNDO.
       newObj = NEW CustUI().
   
       ASSIGN
           newObj:txtCustID   = THIS-OBJECT:txtCustID
           newObj:txtCustName = THIS-OBJECT:txtCustName
           /* (...) */
           .
       RETURN newObj.

    END METHOD.

END CLASS.

Please tell me there is something easier ...

Thank you Mike

Posted by Admin on 20-Jun-2013 03:39

Please tell me there is something easier ...

 

I hope there is no other way! As every other way would break encapsulation - which is one of the basic principles of OO.

In OE11.3 Progress will introduce class level access to private and protected members (http://www.oehive.org/OOWishList). So the Clone method in that class is the only place where you can access also private and protected members.

For .NET serializable objects you could also use the Serializer/Deserializer to copy an object. But that's not accessible for all classes - I doubt a Form is serializable.

Posted by gamerome on 20-Jun-2013 03:54

Wow...so, if I have 100 controls in my form, I have to assign all this one by one?

I need a better solution because I need to clone about 800 different forms. Each form inherits of a super class UI and each form contains tens and tens of controls.

Posted by Admin on 20-Jun-2013 03:58

Wow...so, if I have 100 controls in my form, I have to assign all this one by one?

 

Why do you need to clone a Form with all it's state?

Cloning is for creating an exact copy including all state data.

If you want to open a second (fresh) instance of a Form, just NEW it and show it. The InitializeComponent method in that Form (executed from the Constructor) will create the instances of your 100 Controls.

Posted by gamerome on 20-Jun-2013 04:08

If you want to open a second (fresh) instance of a Form, just NEW it 
and show it. The InitializeComponent method in that Form (executed from
the Constructor) will create the instances of your 100 Controls.

I agree with you but I have trouble with performance.

When I create an instance of my form, I call a custom Initialization method which define the look & feel of each controls. It takes a long time cause this method is recursive.

My idea is to clone an instance which is already initialized and which has already the good look & feel.

And from there, I only just refresh data screen. Thanks to that, performance are really improved.

That's why I need to clone a form.

Posted by jmls on 20-Jun-2013 04:13

I'm just impressed that he has 800 forms, with 100 controls per form.

that's quite a "busy" form ...

Posted by gamerome on 20-Jun-2013 04:21

Labels, UltraEditor, TabControl, etc. Yes some forms are pretty big and that's why it takes few seconds for user to open a form.

This thread is closed