Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant Object comparison

When comparing two objects (of the same type), it makes sense to have a compare function which takes another instance of the same class. If I implement this as a virtual function in the base class, then the signature of the function has to reference the base class in derived classes also. What is the elegant way to tackle this? Should the Compare not be virtual?

class A
{
    A();
    ~A();
    virtual int Compare(A Other);
}

class B: A
{
    B();
    ~B();
    int Compare(A Other);
}

class C: A
{
    C();
    ~C();
    int Compare(A Other);
}
like image 673
mintydog Avatar asked Nov 16 '08 15:11

mintydog


1 Answers

It depends on the intended semantics of A, B, and C and the semantics of compare(). Comparison is an abstract concept that doesn't necessarily have a single correct meaning (or any meaning at all, for that matter). There is no single right answer to this question.

Here's two scenarios where compare means two completely different things with the same class hierarchy:

class Object 
{
    virtual int compare(const Object& ) = 0;
    float volume;
};

class Animal : Object 
{
    virtual int compare(const Object& );
    float age;
};

class Zebra  : Animal 
{
    int compare(const Object& );
};

We can consider (at least) two ways of comparing two Zebras: which is older, and which has more volume? Both comparisons are valid and easily computable; the difference is that we can use volume to compare a Zebra with any other Object, but we can only use age to compare Zebras with other Animals. If we want compare() to implement the age comparison semantics, it doesn't make any sense to define compare() in the Object class, since the semantics aren't defined at this level of the hierarchy. It's worth noting that neither of these scenarios require any casting, whatsoever, as the semantics are defined at the level of the base class (whether it be Object when comparing volume, or Animal when comparing age).

This raises the more important issue -- that some classes aren't suited to a single catch-all compare() function. Often it makes more sense to implement multiple functions that explicitly state what is being compared, like compare_age() and compare_volume(). The definition of these functions can occur at the point in the inheritance hierarchy where the semantics become relevant, and it should be trivial to adapt them to child classes (if the need adapting at all). Simple comparison using compare() or operator==() often only make sense with simple classes where the correct semantic implementation is obvious and unambiguous.

Long story short... "it depends".

like image 88
Kyle Simek Avatar answered Nov 07 '22 22:11

Kyle Simek