user1154644
user1154644

Reputation: 4609

Implementing compareTo() in an abstract class

I have an abstract class in my application (let's call it BaseRule). BaseRule implements the Comparable interface, and contains an abstract method signature public abstract int getExecOrder().

Within the BaseRule implementation of the compareTo() method in the BaseRule class, the return value of getExecOrder() is used to compare the objects.

At present, I have 3 concrete implementations of the BaseRule class, each of which implement the getExecOrder() method

The ultimate purpose of having the BaseRule class implement the Comparable interface is that a Collection of BaseRule objects are passed to a utility that needs to sort these objects to ensure that they are executed in the proper order.

In this case, execution order only matters at the Class level, meaning that every BaseRuleA must be executed before any BaseRuleB is executed, but every BaseRuleB is effectively 'equal' to every other BaseRuleB, so the order that those BaseRuleB objects are processed does not matter

My question is, is there a better way to handle comparing these objects as opposed to using (what I came up with) a getExecOrder() method ?

Right now, I only have 3 concrete implementations of BaseRule so it was easy enough to just assign return values of 1,2,3 to those getExecOrder() method calls, but if another developer adds a new BaseRule implementation, they would have to scan all the existing implementations, and (possibly) update those return values in all of the classes to accommodate the new BaseRule.

Any ideas on a better implementation?

Upvotes: 0

Views: 2409

Answers (2)

jvdmr
jvdmr

Reputation: 715

I honestly think your proposed implementation is the best way to go about this. Definitely add some comments to the abstract getExecOrder() so that future developers know exactly what their implementation of it is supposed to do.

Upvotes: 1

Michael
Michael

Reputation: 44150

I guess you're talking about the following sort of thing?

abstract class BaseRule implements Comparable<BaseRule>
{
    abstract int executionPrecedence();

    @Override
    public int compareTo(final BaseRule that)
    {
        return Integer.compare(this.executionPrecedence(), that.executionPrecedence());
    }
}

class RuleA extends BaseRule
{
    @Override
    int executionPrecedence() { return 0; }
}

class RuleB extends BaseRule
{
    @Override
    int executionPrecedence() { return 1; }
}

It seems fairly reasonable. If you're concerned about having to change the values of existing classes in the future then just leave big gaps rather than using contiguous integers.

A = 10000

B = 20000

C = 30000

Now you have 9999 spaces to place future implementations between these ones.


Maybe also add a unit test which uses reflection to check that no two implementations share the same precedence.

Upvotes: 5

Related Questions