我想定义一个接口,该接口强制进行比较但是针对其特定类型而不是所有父接口类型。
public interface MyInterface extends Comparable<MyInterface>
所以实现的类会自动描述
compare(Subclass x)
而不是
compare(MyInterface)
可能吗?
答案 0 :(得分:2)
你可以这样做:
interface MyInterface<C extends MyInterface<C>> extends Comparable<C> {
}
这将强制实现指定自己的类型,因此:
class MyClass implements MyInterface<MyClass> {
@Override
public int compareTo(MyClass o) {
}
}
但是你必须问自己,你从中获得了什么?
你必须把它传递给:
final MyInterface<MyClass> o = new MyClass();
否则它将是原型。
interface
从类的实现中抽象出来,因此您应该能够传递对MyInterface
的引用,并且每个人都可以访问MyInterface
上定义的方法而无需关心实施班是什么。
只允许在MyClass
和MyClass
之间进行比较,你就完全失去了这种抽象。您强制MyInterface
的任何用户都知道确切的实现,因为比较两个不同的实现会产生ClassCastException
。
您永远无法安全地将MyInterface
与另一个MyInterface
进行比较,除非它们都具有相同的C
- 在这种情况下,您只需将C
与C
进行比较{1}} ...
答案 1 :(得分:1)
我将Boris的想法与泛型一起重用,并将其应用于抽象类。
interface MyInterface extends Comparable<Object> {
}
public abstract class AbstractCompareDelegator<C extends AbstractCompareDelegator<? super C>> implements MyInterface {
@SuppressWarnings("unchecked")
@Override
public final int compareTo(final Object o) {
if (!this.getClass().isAssignableFrom(o.getClass())) {
throw new ClassCastException();
}
return compare(((C) o));
}
protected abstract int compare(final C o);
}
public class FullName extends AbstractCompareDelegator<FullName> {
private final String firstName;
private final String lastName;
public FullName(final String firstName, final String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
protected int compare(final FullName o) {
final int firstNameDiff = firstName.compareTo(o.firstName);
if (firstNameDiff != 0) {
return firstNameDiff;
}
final int lastNameDiff = lastName.compareTo(o.lastName);
if (lastNameDiff != 0) {
return lastNameDiff;
}
return 0;
}
@Override
public String toString() {
return String.format("FullName [firstName=%s, lastName=%s]\n", firstName, lastName);
}
public static void main(final String[] args) {
final Collection<MyInterface> orderedNames = new TreeSet<MyInterface>();
// add names unordered
final MyInterface name1 = new FullName("Luke", "Skywalker");
orderedNames.add(name1);
final MyInterface name2 = new FullName("Joe", "Black");
orderedNames.add(name2);
final MyInterface name3 = new FullName("Forest", "Gump");
orderedNames.add(name3);
final MyInterface name4 = new FullName("John", "Rambo");
orderedNames.add(name4);
// was the set ordered?
System.out.println(orderedNames);
}
}
Output:
[FullName [firstName=Forest, lastName=Gump]
, FullName [firstName=Joe, lastName=Black]
, FullName [firstName=John, lastName=Rambo]
, FullName [firstName=Luke, lastName=Skywalker]
]