简体   繁体   中英

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

I want to use an interface 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, eg FloatResult implementing ResultItem<IntResult> but it makes various bits of API work when all the classes are well behaved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM