一种创建接口扩展比较器接口的方法,该接口仅比较当前子类

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 是什么。

只允许在 MyClassMyClass 之间进行比较,你就完全失去了这种抽象。您强制 MyInterface 的任何用户知道确切的实现,因为比较两个 不同的 实现会导致 ClassCastException.

你永远无法安全地将 MyInterface 与另一个 MyInterface 进行比较,除非它们具有相同的 C - 在这种情况下你可以只比较 CC...

我在泛型中重用了 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.
  • 的实例