开发者

How can I make an interface instance method accept arguments of the same class only?

I want to use an inter开发者_开发百科face like this :

public interface ResultItem {
    public int getConfidence();
    public boolean equals(ResultItem item);
    public ResultItem cloneWithConfidence(int newConfidence);
}

I have it implemented by different kind of objects representing a voice recognition result.

The idea is, I wish to compare only results of the same kind. That is, if I create a class IntResult implementing ResultItem, I want that the method signatures become :

public boolean equals(IntResult item);
public IntResult cloneWithConfidence(int newConfidence);

I feel that there is a design flaw in my interface, because for now I am using pretty ugly casts on the results of cloneWithConfidence and of other methods returning a ResultItem.

Is there a better way?


There is a frequently-seen idiom that goes as follows:

public interface ResultItem<T extends ResultItem<T>> {
    public int getConfidence();
    public boolean equals(T item);
    public T cloneWithConfidence(int newConfidence);
}

public class IntResult implements ResultItem<IntResult> {
  //...
}


Not really an answer to your question, but an important remark (I think):

If you want your equals-method to be usable for objects in collections and similar, you need to implement public boolean equals(Object o), and it should work for comparisons to all kinds of objects (in most cases returning false, though). You may have additionally a method with a narrower parameter type, and in implementations delegate like this:

public class IntResult {
    public boolean equals(Object o) {
        return o instanceof IntResult &&
             this.equals((IntResult)o);
    }
    public boolean equals(IntResult that) {
        // TODO
    }

}

Make sure you comply to all the conditions in the contract of equals, namely symmetry, reflexivity, transitivity and having a compatible hashCode implementation.


Well, you could make it generic:

public interface ResultItem<T extends ResultItem<T>> {
    public boolean equals(ResultItem<T> item);
}

Then you would need to make IntResult implement ResultItem<IntResult>.

Of course that doesn't stop another class from misbehaving, e.g. FloatResult implementing ResultItem<IntResult> but it makes various bits of API work when all the classes are well behaved.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜