Question

I have an abstract Dice class and there are some concrete subclasses like SixFacesDice, TwentyFacesDice, etc... I want every Dice object to be comparable with an other but only if it is of the same subclass (e.g. a SixFacesDice can't be compared with a TwentyFacesDice) but I wouldn't to implement Comparable for every subclass.

The only way I see is to implement Comparable with Dice class and check if objects are of the same class, otherwise return 0. But this method is not elegant at all... Is there some method or design pattern to solve this?

Was it helpful?

Solution

Assuming you want compile-time safety rather than just execution-time safety, you could use generics, like this:

abstract class Dice<T extends Dice> implements Comparable<T> {
    int value;

    public int compareTo(T other) {
        return Integer.compare(value, other.value);
    }
}

final class Dice1 extends Dice<Dice1> {
}

final class Dice2 extends Dice<Dice2> {
}

That wouldn't stop someone from abusing it like this:

class BadDice extends Dice<Dice1>

... but when used properly, I think it gives you the behaviour you want.

Note that this only works with one inheritance level, too - you wouldn't be able to cleanly have a subclass of a subclass of Dice<T>, because then your "same class" enforcement would fail.

If you're fine with just execution-time safety, then comparing this.getClass() with other.getClass() is absolutely reasonable.

OTHER TIPS

Elegant or not, comparing the result of getClass() is standard practice. Except that you shouldn't return 0 but instead throw a ClassCastException. Returning 0 does not signal "not comparable", but "equal", and that relation has certain constraints you cannot meet with that design, such as transitivity:

DiceA aLow, aHigh;
DiceB b;

In your case,

aLow.compareTo(b) == b.compareTo(aHigh) == 0

but

aLow.compareTo(aHigh) < 0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top