4

这个SO 讨论提出了以下成语:

public interface IComparable<T extends IComparable<T>> {
    int compare(T t);
}

然后允许:

public class Foo implements IComparable<Foo> {
    public int compare(Foo foo) {
        return 0;
    }
}

然而,这个习语不仅仅允许上面的,因为下面的代码也可以编译:

class A implements IComparable<A> {
    public int compare(A a) {return 0;}
}

public class Foo implements IComparable<A> {

    public int compare(A a) {
        return 0;
    }
}

因此(除非我误解了某些东西)原始的成语并没有真正买更多的东西,而不是戏剧性的:

public interface IComparesWith<T> {
    int compare(T t);
}

public class A implements IComparesWith<A> {
    public int compare(A a) {...}
}

那么,有没有一种方法可以实际声明一个接口,使得任何声明实现它的类都有一个方法来与它自己的类的对象进行比较,而没有任何上述漏洞?

我显然无法将以上内容作为评论发布,因此我创建了一个新帖子。

4

5 回答 5

6

不,这种限制对于所写的泛型是不可能的。你的评估对我来说似乎是正确的。

于 2013-08-31T23:09:50.103 回答
5

你是对的:这个习语并没有阻止将类与不同的类进行比较。它所做的只是确保比较对象也实现相同的接口。如果需要仅比较相同的类型,则可以由实现类强制执行。

你所说的“漏洞”就是我所说的“故意做你不想做的事情”。

如果需要这种行为,可以将Foo对象与A对象进行比较。

这是一个特点,而不是一个漏洞。

如果您希望Foo与其他 Foo 具有可比性则应定义Foo来实现IComparable<Foo>

如果您希望FooA具有可比性,那么您不应该定义Foo来实现IComaparable<A>。除非他们故意尝试编写损坏的代码,否则为什么会有人这样做?

@caskey 已经提供了您问题的实际答案:

不,你不能在 Java 中使用接口做你想做的事。[你必须用类来做]。

你错过了一件事:

因此(除非我误解了某些东西)原始的成语并没有真正买更多的东西,而不是戏剧性的:

public interface IComparable<T>

原来的成语 确实给你买了东西。它强制比较对象必须实现IComparable。不太引人注目的示例将允许您不受限制地将实现类与任何对象进行比较。所以...编译器将允许您指定Long, or InputStream, or LinkedHashSet<Byte[]>, 或任何东西作为类型参数。

当你这样看时,很容易看出为什么这个成语如此普遍。

于 2013-09-01T01:04:18.207 回答
3

因此(除非我误解了某些东西)原始的成语并没有真正买更多的东西,而不是戏剧性的:

它确实购买了一些东西,但它与您的想法不同。当有人这样写时,99.9% 的情况下这不是他们想要购买的东西。

那么,有没有一种方法可以实际声明一个接口,使得任何声明实现它的类都有一个方法来与它自己的类的对象进行比较,而没有任何上述漏洞?

不,因为它在类型安全方面没有用。没有任何问题public class Foo implements IComparable<A>- 它是完全类型安全的。如果有人想以某种方式Foo安全地进行比较A,那就太好了。我同意 jahroy'a 的回答——这不是“漏洞”;这是一个特点。为什么让它更通用,只要它是安全的?它不会妨碍你正在做的任何事情。如果你想让你的所有课程都与自己进行比较,那也没关系。一切都很好,只要它是类型安全的。

您应该关心关于类型和实现它的类型参数的关系的唯一地方IComparable您使用它的地方,因为那个地方可能合法地需要这种关系。所以在那个地方(由可比较类型参数化的泛型类或泛型方法),我们可以很容易地绑定表示可比较类型的类型变量,如下所示:T extends IComparable<? super T>,允许我们保证T可以与自身进行比较。

于 2013-09-01T02:02:24.263 回答
-1

不要使用泛型:

public interface Foo {
    public void doSomething(Foo foo);
}
于 2013-08-31T23:05:37.077 回答
-4

确实。我主张我们使用This此类类型参数的常规名称

public interface IComparesWith<This> 
{
    int compare(This t);
}

我之前的回答:编写指向其实现者的通用接口的便捷方式

于 2013-08-31T23:21:01.567 回答