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.
精彩评论