我怎样才能使接口实例方法只接受同一个类的参数,真的吗?

时间:2013-08-31 23:02:48

标签: java generics interface

SO discussion提出以下习语:

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) {...}
}

那么,有没有办法实际声明一个接口,这样无论什么类声明实现它都有一个方法来与它自己的类的对象进行比较,没有任何上面的漏洞?

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

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:5)

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

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

Foo 对象可以与 A 对象进行比较 IF 需要这样的行为。

这是一个功能,而不是漏洞。

如果您希望 Foo 与其他 Foos 相媲美,则应定义 Foo 以实现IComparable<Foo>

如果希望 Foo A 相媲美,那么不应该定义 Foo 实施IComaparable<A>。为什么有人会这样做,除非他们故意写故障代码?

问题的实际答案已由@caskey提供:

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

你错过了一件事:

  
    

因此(除非我误解了某些东西)原来的成语并没有真正购买任何东西,而不是那么戏剧化:

  

public interface IComparable<T>

原始成语 确实为您买东西。它强制比较的对象必须实现 IComparable 。不那么引人注目的例子允许您无限制地将实现类与任何对象进行比较。所以...编译器允许您指定LongInputStreamLinkedHashSet<Byte[]>或任何类型参数。

当你以这种方式看待它时,很容易理解为什么这个成语如此常见。

答案 2 :(得分:3)

  

因此(除非我误解了某些东西)原来的成语   与不那么引人注目的相比,它并没有真正购买任何东西:

它确实买了东西,但它与你想到的不同。当有人写这篇文章时,99.9%的时间并不是他们想要购买的东西。

  

那么,有没有办法实际声明一个接口,无论如何   class声明实现它有一个方法来与对象进行比较   它自己的班级,没有任何上面的漏洞吗?

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

您应该关注类型与其实现IComparable的类型参数之间关系的唯一地方是您使用它,因为该地点可能合法地需要对于这种关系。所以在那个地方(通过类似的类型参数化的泛型类或泛型方法),我们可以很容易地绑定代表类似类型的类型变量:T extends IComparable<? super T>,允许我们保证{{1}可以比较自己。

答案 3 :(得分:-1)

不要使用泛型:

public interface Foo {
    public void doSomething(Foo foo);
}

答案 4 :(得分:-4)

事实上。我主张我们使用This作为此类型参数的常规名称

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

我之前的回答:Convenient way to write generic interface that points out to its implementor