www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opEquals for multiple types

reply Wouter Verhelst <wouter grep.be> writes:
Hi,

I'm trying to implement opEquals. I had originally done something like

class foo : bar {
      bool opEquals(bar e) {
           ... code here ...
      }
      bool opEquals(foo e) {
           ... somewhat more specialized code here ...
      }
}

(where bar is an interface)

but that gave me a message about how hiding Object.opEquals is
deprecated.

My next attempt was to add a

      bool opEquals(Object o)

which would then decide which opEquals function to call based on what
typeid() on the Object returns. But since I want to have a version
involving an interface, that's not going to fly.

What's the best way forward?

-- 
The volume of a pizza of thickness a and radius z can be described by
the following formula:

pi zz a
Jul 08 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, July 08, 2012 10:56:25 Wouter Verhelst wrote:
 Hi,
 
 I'm trying to implement opEquals. I had originally done something like
 
 class foo : bar {
       bool opEquals(bar e) {
            ... code here ...
       }
       bool opEquals(foo e) {
            ... somewhat more specialized code here ...
       }
 }
 
 (where bar is an interface)
 
 but that gave me a message about how hiding Object.opEquals is
 deprecated.
 
 My next attempt was to add a
 
       bool opEquals(Object o)
 
 which would then decide which opEquals function to call based on what
 typeid() on the Object returns. But since I want to have a version
 involving an interface, that's not going to fly.
 
 What's the best way forward?

For classes, opEquals _must_ take Object. It can't take anything else. If you want to do something differently for specific base classes, you're going to need to deal with it within opEquals via casting. However, that's _still_ not likely to do what you want, because D ensures that equality goes in _both_ directions, so if the types differ, opEquals must be true for both a.opEquals(b) and b.opEquals(a). You can't have only one side deciding that it's equal to the other. They have to agree. - Jonathan M Davis
Jul 08 2012
prev sibling parent Wouter Verhelst <wouter grep.be> writes:
Jonathan M Davis <jmdavisProg gmx.com> writes:

 On Sunday, July 08, 2012 10:56:25 Wouter Verhelst wrote:
 Hi,
 
 I'm trying to implement opEquals. I had originally done something like
 
 class foo : bar {
       bool opEquals(bar e) {
            ... code here ...
       }
       bool opEquals(foo e) {
            ... somewhat more specialized code here ...
       }
 }
 
 (where bar is an interface)
 
 but that gave me a message about how hiding Object.opEquals is
 deprecated.
 
 My next attempt was to add a
 
       bool opEquals(Object o)
 
 which would then decide which opEquals function to call based on what
 typeid() on the Object returns. But since I want to have a version
 involving an interface, that's not going to fly.
 
 What's the best way forward?

For classes, opEquals _must_ take Object. It can't take anything else.

Ah. Well, that explains that.
 If you 
 want to do something differently for specific base classes, you're going to
need 
 to deal with it within opEquals via casting. However, that's _still_ not 
 likely to do what you want, because D ensures that equality goes in _both_ 
 directions, so if the types differ, opEquals must be true for both 
 a.opEquals(b) and b.opEquals(a). You can't have only one side deciding that 
 it's equal to the other. They have to agree.

Right. Having thought about it some more, I've come to the conclusion that opEquals is probably not what I need. I have a class NodeTemplate that defines a number of properties that a particular node in my data structure needs to conform to. It need not fully specify each and every property of the node (that's why it's called a "template"), but it does need to match on the properties that are specified. The NodeTemplate class has a private member of type TypeInfo, and knows how to instantiate an object given some context and the properties it knows about. Since it's not a full description, "equality" is probably not a good concept to apply to this particular comparison. As such, I've implemented it as a "matches()" function, which takes an argument of the interface shared by these objects, and can do some inflection etc to see if the object would be okay according to this template. That works, and it's probably cleaner too. Never the less, thanks for your explanations; it did clarify things a bit. -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a
Jul 09 2012