一种创建接口扩展比较器接口的方法,该接口仅比较当前子类
A way to create an interface extending comparator interface that compares current subclass only
我想定义一个接口,它强加比较但针对其特定类型而不是所有父接口类型。
public interface MyInterface extends Comparable<MyInterface>
所以实现的类会自动描述
compare(Subclass x)
而不是
compare(MyInterface)
这可能吗?
你可以这样做:
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();
否则就是rawtype。
interface
从 class 的实现中抽象出来,因此您应该能够传递对 MyInterface
的引用,并且每个人都能够访问定义在MyInterface
不关心实现 class 是什么。
只允许在 MyClass
和 MyClass
之间进行比较,你就完全失去了这种抽象。您强制 MyInterface
的任何用户知道确切的实现,因为比较两个 不同的 实现会导致 ClassCastException
.
你永远无法安全地将 MyInterface
与另一个 MyInterface
进行比较,除非它们具有相同的 C
- 在这种情况下你可以只比较 C
至 C
...
我在泛型中重用了 Boris 的想法,并将其应用于抽象 class。
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]
]
- 我在具体 class 和接口之间应用了抽象 class。
- 我没有在界面限制基因类型。我把它留作对象。我在摘要 class compareTo()
中做了限制
- 我将 compareTo() 从抽象 class 委托给具体的 subclass compare() 以用具体的 class 参数覆盖。
- 现在您可以使用 MyInterface 来引用具体的子class,而不需要在引用类型中提及任何泛型。
- 您应该小心使用 MyInterface,因为无法比较对不同 classes 的实例的引用(它会抛出 ClassCastException,如先前评论中所述)
- 在我的示例中,您失去了在具体 class 中扩展其他 class 的可能性,因为它已经扩展了技术摘要 class。这不好。
- 您可以组织 MyInterface 对不同集合的引用,但不要对它们进行排序!在排序之前确保它们是相同 class.
的实例
我想定义一个接口,它强加比较但针对其特定类型而不是所有父接口类型。
public interface MyInterface extends Comparable<MyInterface>
所以实现的类会自动描述
compare(Subclass x)
而不是
compare(MyInterface)
这可能吗?
你可以这样做:
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();
否则就是rawtype。
interface
从 class 的实现中抽象出来,因此您应该能够传递对 MyInterface
的引用,并且每个人都能够访问定义在MyInterface
不关心实现 class 是什么。
只允许在 MyClass
和 MyClass
之间进行比较,你就完全失去了这种抽象。您强制 MyInterface
的任何用户知道确切的实现,因为比较两个 不同的 实现会导致 ClassCastException
.
你永远无法安全地将 MyInterface
与另一个 MyInterface
进行比较,除非它们具有相同的 C
- 在这种情况下你可以只比较 C
至 C
...
我在泛型中重用了 Boris 的想法,并将其应用于抽象 class。
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]
]
- 我在具体 class 和接口之间应用了抽象 class。
- 我没有在界面限制基因类型。我把它留作对象。我在摘要 class compareTo() 中做了限制
- 我将 compareTo() 从抽象 class 委托给具体的 subclass compare() 以用具体的 class 参数覆盖。
- 现在您可以使用 MyInterface 来引用具体的子class,而不需要在引用类型中提及任何泛型。
- 您应该小心使用 MyInterface,因为无法比较对不同 classes 的实例的引用(它会抛出 ClassCastException,如先前评论中所述)
- 在我的示例中,您失去了在具体 class 中扩展其他 class 的可能性,因为它已经扩展了技术摘要 class。这不好。
- 您可以组织 MyInterface 对不同集合的引用,但不要对它们进行排序!在排序之前确保它们是相同 class. 的实例