Is there anything in this release that helps manage collections ? I was able to compile the following, and was living in hope for a few seconds ..
DEF PUBLIC PROPERTY Node AS CLASS node EXTENT NO-UNDO GET . PRIVATE SET .
node[1] = new node ().
node[1]:text = "foo".
message node[1]:Text view-as alert-box.
so, it all compiles. But when you run, you get message 11389. Bummer ; It would have made collections easy !
Maybe you could use a temp-table of Progress.Lang.Object and write your own class methods like for example with System.Collections.ArrayList?
maybe - I was hoping that PSC would allow me to do it the easy way
What you tried in your code was not Collection support. It was support for property indexers... AFAIK that has been discussed and delayed for a later release.
I can live with that FOR NOW...
Why don't you go with any of the .NET collection classes? Even ABL classes, that inherit from System.Object or any other appropriate .NET class can be added to those collections and lists.
What you tried in your code was not Collection
support. It was support for property indexers...
AFAIK that has been discussed and delayed for a later
release.
Thanks for the enlightenment.
I can live with that FOR NOW...
Why don't you go with any of the .NET collection
classes? Even ABL classes, that inherit from
System.Object or any other appropriate .NET class can
be added to those collections and lists.
So, if I were to add a number of 4GL classes (let's say my "node" class) how would I access them
In VB I would say TopClass.Nodes.Item(n).Text or even TopClass.Nodes(n).text
so, if I made "Nodes" a VB collection and added my "nodes" class to the collection I would be able to say
TopClass:Nodes:Item(n):Text or TopClass:Nodes(n):Text ?
* jmls rushes off to try
Why don't you go with any of the .NET collection
classes? Even ABL classes, that inherit from
System.Object or any other appropriate .NET class can
be added to those collections and lists.
Huh, so System.Collections.ArrayList works for ABL classes as well!
DEFINE VARIABLE r1 AS CLASS System.Collections.ArrayList.
DEFINE VARIABLE r2 AS CLASS test.
r1 = NEW System.Collections.ArrayList().
r2 = NEW test().
r1:ADD(r2).
r2 = NEW test().
r1:ADD(r2).
MESSAGE r1:item[1]:equals(r2) /* yes */
VIEW-AS ALERT-BOX INFO BUTTONS OK.
/* test.cls */
CLASS test INHERITS System.OBJECT.
END CLASS.
are you saying that this works, or doesn't ?
i don't know, if there is an issue. Are you aware that .NET starts to count at 0?
heh. That's what I was alluding to.
If it works it's another reason to have support for .NET in the appserver (after FCS offcourse.)
And if the support would also work for mono it would even work on unix appservers! But I'm probably asking a lot now...
Maybe you could use a temp-table of Progress.Lang.Object and write your own class methods
Something like this, you mean?
http://www.oehive.org/CollectionClasses
Yes, it works...
But the DYNAMIC-CAST does not work anyone knows why?
DEFINE VARIABLE rArray AS CLASS System.Collections.ArrayList.
DEFINE VARIABLE rTest1 AS CLASS test1.
DEFINE VARIABLE rTest2 AS CLASS test2.
DEFINE VARIABLE rObj AS CLASS System.OBJECT.
DEFINE VARIABLE j AS INTEGER NO-UNDO.
/* create */
rArray = NEW System.Collections.ArrayList().
rTest1 = NEW test1().
rArray:ADD(rTest1).
rTest2 = NEW test2().
rArray:ADD(rTest2).
/* be aware that .NET starts to count at 0 */
DO j = 0 TO rArray:COUNT - 1:
MESSAGE
rArray:ITEM:tostring()
rArray:ITEM:equals(rTest2)
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.
/* pick a random item */
rObj = rArray:ITEM.
/* cast to correct type and call method */
DYNAMIC-CAST(r3, rObj:tostring()):testme(). /* error */
/CAST(rObj, "test1"):testme()./
/* test1.cls
CLASS test1 INHERITS System.OBJECT.
METHOD PUBLIC VOID testme():
MESSAGE THIS-OBJECT:tostring()
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END METHOD.
END CLASS.
*/
/* test2.cls
CLASS test2 INHERITS System.OBJECT.
METHOD PUBLIC VOID testme():
MESSAGE THIS-OBJECT:tostring()
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END METHOD.
END CLASS.
*/
Maybe you could use a temp-table of
Progress.Lang.Object and write your own class methods
Something like this, you mean?
http://www.oehive.org/CollectionClasses
Exactly. But I guess to can use the System.Collections as well...
Hi Julian,
This should work since it is just an ABL array of .NET classes. In your code snippet, the array has not been initialized to a size so it doesn't have any "storage area" yet. You need to set the extent (size) before doing the assignment:
node[1] = new node ().
And since this is an ABL array, not a .NET array, it's index starts at 1.
Like others are saying, you can put .NET classes in ABL arrays but you cannot put ABL classes into .NET arrays/collections.
-Shelley
Like others are saying, you can put .NET classes in
ABL arrays but you cannot put ABL classes into .NET
arrays/collections.
Hi Shelley,
so, is adding an ABL class that inherits from System.Object something that will NOT be supported? It works too well for me to believe!
I always thought, that an ABL class that inherits from a .NET type can be used anywhere the base .NET type can be used. But for the .NET side of the bridge, the ABL class will look exactly like the .NET class, so extending members from the ABL side will not be visible on the .NET side.
The whole inheritance from .NET controls would be completly useless, if I could not add ABL classes (inherting at least from System.Object) to the Controls (well here it should be System.Windows.Forms.Control) collection of a Form or the Items collection of a ComboBox.
Or am I misundertanding your statement, as you do not consider an ABL class that inherits from System.Object an ABL class anymore?
Mike (confused)
Note on the AppServer. There's where you need something home grown like Thomas' Collection classes or something similar (i.e. based on a temp-table with a Progress.Lang.Object field).
Hi Mike,
Sorry for the confusion. You can inherit from .NET classes in the ABL. And from .NET, they look like they were written in .NET.
I was trying to make the point that a class that is pure ABL and does not have System.Object in its class hierarchy cannot be used as a .NET object. For example a pure ABL class cannot be put into a System.Array. Make sense?
-Shelley
Absolutely.
Looks like we need a good name for ABL classes inheriting from System.Object to avoid confusion. I still consider them ABL classes as the majority of the creativity that I spend on making them what they are is developed in ABL code. While in the ABL, the .NET part is a black (or at least dark grey) box.
How about a hybrid or magic class
Mike (a stone has fallen off my heart!)
I believe the documentation for 10.2A will refer to them as a hybrid user-defined class or hybrid class for short.
How about ABL.NET class?
(I am just a simple mind)
I like simple minds (forget about me!)
ABL.NET get's my vote!
Note on the AppServer. There's where you need
something home grown like Thomas' Collection classes
or something similar (i.e. based on a temp-table with
a Progress.Lang.Object field).
Understood.
Any idea why the DYNAMIC-CAST does not work?
DYNAMIC-CAST(r3, rObj:tostring()):testme(). /* error */
-or-
DYNAMIC-CAST(r3, "test1"):testme(). /* error */
How about ABL.NET class?
(I am just a simple mind)
+1
got my vote aswell, clear and simple.
First: I don't see a variable definition for r3, so I don't know it's type.
Second: rObj:ToString() returns (if not overridden somewhere) a pseudo reference value that consists of the type name and something like a handle. So it can't be a string returning the type/class name.
Dynamic cast requires a valid type name. As it's second argument.
By the way: I don't thing I'll ever use/need DYNAMIC-CAST at all! At least as long as we don't have dynamic invokation of methods in the ABL at all. The combination of TYPE-OF and CAST works better for me.
DYNAMIC-CAST(r3, "test1"):testme(). /* error */
Quote from the reference (online help):
"You cannot use the DYNAMIC-CAST function to cast an object reference to a subclass and invoke a method defined in that subclass using the following syntax:"
I guess this is because the compiler can not know the sub-class that will be passed at runtime and so it can't know anything about validity of the testme() method.
No chance to break strong typing with DYNAMIC-CAST! Great, isn't is?
Sorry, r3 should be rObj:
DYNAMIC-CAST(rObj, rObj:tostring()):testme(). /* error */
In the example rObj:ToString() returns either "test1" or "test2".
I thought this could be done dynamically by a one-liner but I guess the only way to do this is like you said with the TYPE-OF and CAST for each type of class in the array of System.Object.
IF TYPE-OF(rObj, "test1") THEN
CAST(rObj, "test1"):testme().
IF TYPE-OF(rObj, "test2") THEN
CAST(rObj, "test2"):testme().
...
IF TYPE-OF(rObj, "testN") THEN
CAST(rObj, "testN"):testme().
Is it that the dynamic cast fails or is it that you are trying to run a method on the dynamic cast result that fails. What happens if you move the testme() to a second line?
Doesn't work. You have to cast again to make it work...
DEFINE VARIABLE rTmp AS CLASS System.OBJECT.
rTmp = DYNAMIC-CAST(rObj, rObj:ToString()).
rTmp:testme(). /* Could not locate element 'testme' in class 'System.OBJECT'. (12927) */
CAST(rTmp, "test1"):testme(). /* ok */
So, in this sequence, it compiles, but fails in execution on the testme line? That seems very peculiar indeed. One would expect the dynamic-cast to either produce a result or to throw an error.
The following syntax is not allowed:
DYNAMIC-CAST( object-reference, object-type-name ):method-name( parameters ).
So once you have dynamically cast the object you have to do a static CAST again to be able to call the method testme().
So I think this means you cannot use the ArrayList class in a generic way to store ABL classes without knowing in advance what exact classes you are using. If you are going to call methods in those classes that is...
Ah well, it is more likely you know in advance the exact classes and use TYPE-OF and a static CAST to call the methods anyway... (like Mike said a few posts back)
I would like to see a good example of the DYNAMIC-CAST statement though...
A good example is right ... from that code, it is not clear what, if anything, the dynamic cast is actually doing.
I would like to see a good example of the
DYNAMIC-CAST statement though...
I owe you a beer for this question!
I really see no need why we have the DYNAMIC-CAST function in the ABL. But maybe all the customers using OOABL in this forum are just blind here.