Implementing an Equals() override

Posted by Peter Judge on 15-Jan-2010 13:50

Has anyone given thought to - or even better yet, implemented - overriding Equals in a PABLO*? Ideally the method should be capable of dealing with objects, as well as primitives, and also data structures like temp-tables etc.

Serialisation is an option, but it's more appropriate to cloning than identity comparisons.

Some of MSDN's thoughts on the matter here ; some of IBM's here.

-- peter

* Plain ABL Object

All Replies

Posted by Thomas Mercer-Hursh on 15-Jan-2010 14:07

How could equals ever be anything but type specific ... or am I getting you wrong?

Posted by Peter Judge on 15-Jan-2010 14:12

tamhas wrote:

How could equals ever be anything but type specific ... or am I getting you wrong?

Equals() is instance-specific AFAIK. Of course, I may be wrong (that has occasionally happened ) but I'm still interested in a fast value equality method.

An easy way to check type equality is to use RCODE-INFO:MD5-value, incidentally.

-- peter

Posted by Thomas Mercer-Hursh on 15-Jan-2010 15:14

Just to be careful ....

Equality means:

1. Same type, i.e., class or subclass.

2. Same version of class (where your MD5 comes in)

3. Same data members.  <<>>

The first two seem simple and the last one tedious.  Now, if you guys would give us WRITE-XML for a class, then one could do that for both and simply compare whether the results were identical.

Baring something built-in, if one had implemented a method which would do the logical equivalent of WRITE-XML, that would seem a good way to do it.

Posted by Peter Judge on 15-Jan-2010 15:41

Equality means:

1. Same type, i.e., class or subclass.

2. Same version of class (where your MD5 comes in)

3. Same data members.

I'd modify this to say "same state of object", since the existence of the members (i.e. behaviour) is covered by 1 & 2.

Also, equality can mean

4. Same instance of an object

#3 is what I'm looking for (assuming 10.2B). I can do it via serialization ("WRITE-XML") but that's potentially slow and overkill.

-- peter

Posted by Admin on 15-Jan-2010 15:41

What's makes you believe you know what makes two instances of my

classes 'equal'?

If it would be so easy Equal() might be defined on

Progress.Lang.Object as FINAL?

Posted by Peter Judge on 15-Jan-2010 15:44

What's makes you believe you know what makes two instances of my

classes 'equal'?


I don't, of course. I'm looking for general strategies or approaches, to implement in my own classes.

There certainly are some defaults, such as objRef1 being the same as objRef2 that do satisfy some level of equality, which could be implemented in PLO, but this isn't easy to generalise, for sure.

-- peter

Posted by Admin on 15-Jan-2010 15:56

as well as primitives, and also data structures like temp-tables etc.

 

An Equals() method on primitives? Tell me more about that! Or do you mean more a static helper class than can compare two primitives or a method of a class that compares an instance to a primitive?

Posted by Admin on 15-Jan-2010 15:56

but this isn't easy to generalise, for sure.

 

Certainly that's true. I'd wish further some sort of annotations that could mark relevant data members for comparison.

One example: Two instances (of the same class) both have a (dynamic) buffer for the customer table, both pointing at the same record. The buffers handles (the actual data members, I'd say) are different values. I'd still consider both instances as equal (as equal in state or knowledge).

A too generic approach would probably return NOT equal.

Posted by Thomas Mercer-Hursh on 15-Jan-2010 16:12

Yes, I meant value, not that the same data members existed.

Same instance would be covered by same handle, no?

That seems to me to be the trivial case.  Much more interesting is something being a perfect clone, but not the same object.

Performance is testable on WRITE-XML versus pair-wise comparisons ... or it would be if we had WRITE-XML.  It appeals to me because it is three operations and highly standardized, i.e., WRITE-XML of other, WRITE-XML of self, compare.  Pairwise comparisons have the advantage of stopping after the first mismatch.  Note that every property comparison on the other object implies the equivalent of a getter method call.

Interesting possible issue, if WRITE-XML serializes state or one has a hand-coded method that serializes state, the contents of the output are not equivalent to testing all externally visible properties.  The externally visible properties can include some that are computed and thus redundant and there may be internal properties which are an important part of state, which are not publically visible.

This seems to suggest that one has to test the serialization since only it is going to have all the internal state and only the internal state.

Posted by Peter Judge on 15-Jan-2010 16:16

Certainly that's true. I'd wish further some sort of annotations that could

mark relevant data members for comparison.

Indeed that would help. But if you implement your own Equals() you decide this. Annotations would help with reflection (say) being used for equality checks.

I'd still consider both instances as equal (as equal in state or knowledge).

Exactly.

A too generic approach would probably return NOT equal.

Right. A extremely-generic approach might just compare buffer handle values. Which wouldn't work niceluy at all

An Equals() method on primitives? Tell me more about that! Or do you mean

more a static helper class than can compare two primitives

This one. And again, what a class considers necessary for equality depends on that class and its developers.

-- peter

Posted by Thomas Mercer-Hursh on 15-Jan-2010 16:18

Annotations, maybe, but also some logic.  I.e., if one of the primary purposes of serialization is to send things across the wire, then serializing the buffer handle is obviously meaningless ... so what is one going to serialize?  For a statis buffer, it might be the ROWID.  For a dynamic buffer on a DB table, it might be the _File number and the ROWID.  But, gosh, if it is a dynamic buffer on a temp-table which is not even contained in the object ... what in the world would one send?  (btw, that is something which will be coming up in the M-S-E discussion or I might not have thought about it).

Posted by Admin on 15-Jan-2010 16:36

And again, what a class considers necessary for equality depends on

that class and its developers.

Amen!

Posted by Admin on 15-Jan-2010 16:46

Back at 2K points. Congrats, Dr. Thomas!

Posted by Thomas Mercer-Hursh on 15-Jan-2010 16:52

Out of nearly 2.5K posts, however!

Posted by Peter Judge on 19-Jan-2010 11:40

Same instance would be covered by same handle, no? That seems to me to be the trivial case. 


Agreed, but included for completeness' sake.

Much more interesting is something being a perfect clone, but not the same object.

Cloning and/or serialization is a completely different kettle of wax. Interesting, certainly, but different.

*For equality*, it would be nice to have an ABL property that returns a hash/crc value on a temp-table which reflects the contents of that table. Maybe a hash of the rowid's or something (just off the top of my head).

Performance is testable on WRITE-XML versus pair-wise comparisons ... or it would be if we had WRITE-XML.  It appeals to me because it is three operations and highly standardized, i.e., WRITE-XML of other, WRITE-XML of self, compare.  Pairwise comparisons have the advantage of stopping after the first mismatch.  Note that every property comparison on the other object implies the equivalent of a getter method call.

As Mike pointed out, there's no easy (if any) way of generically determining what constitutes equality for a type.  I believe that other languages use annotations for (some of) this functionality, but that's not currently available to us in the ABL today.

-- peter

This thread is closed