简体   繁体   English

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

[英]How can I make an interface instance method accept arguments of the same class only, really?

This SO discussion proposes the following idiom: 这个SO讨论提出了以下习语:

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

which then allows: 然后允许:

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

However, this idiom allows more than just the above as the following code compiles as well: 但是,这个习惯用法不仅仅包括以上代码,因为下面的代码也可以编译:

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;
    }
}

Therefore (unless I've misunderstood something) the original idiom doesn't really buy anything more compared to the far less dramatic: 因此(除非我误解了一些东西)原始成语并没有真正购买任何东西,而不是那么戏剧化:

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

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

So, is there a way to actually declare an interface such that whatever class declares to implement it has a method to compare with objects of its own class, without any loopholes such the one above? 那么,有没有办法实际声明一个接口,以便任何类声明实现它有一个方法来与它自己的类的对象进行比较,没有任何漏洞,如上所述?

I obviously could't post the above as a comment hence I created a new post. 我显然无法将上述内容发布为评论,因此我创建了一个新帖子。

No, that sort of restriction is not possible with the generics as written. 不,这样的限制是不可能用写的泛型。 Your assessment seems correct to me. 您的评估对我来说似乎是对的。

You are correct: this idiom does not prevent classes from being compared to different classes. 你是正确的:这个成语并不阻止比较不同类的类。 All it does is ensure that the compared object also implements the same interface. 它所做的只是确保比较对象也实现相同的接口。 If there is a requirement to only compare the same types, that can be enforced by the implementing class. 如果只需要比较相同类型,则可以由实现类强制执行。

What you call a " loophole " is what I would call " intentionally doing something you don't want to do ". 你称之为“ 漏洞 ”的是我所谓的“ 故意做你不想做的事情 ”。

Foo objects can be compared to A objects IF such behavior is desired. 如果需要这样的行为,可以将Foo对象与A对象进行比较。

This is a feature, not a loophole. 这是一个功能,而不是漏洞。

If you want Foo to be comparable to other Foos , you should define Foo to implement IComparable<Foo> . 如果你想让Foo与其他Foos相媲美,你应该定义Foo来实现IComparable<Foo>

If you don't want Foo to be comparable to A , then you shouldn't define Foo to implement IComaparable<A> . 如果您希望FooA相媲美,那么您不应该定义Foo来实现IComaparable<A> Why would anybody do that unless they were trying to write broken code on purpose? 为什么有人会这样做,除非他们故意写破坏的代码?

The actual answer to your question has already been provided by @caskey: 你的问题的实际答案已经由@caskey提供:

" No, you can't do what you want using interfaces in Java. [You have to do it with classes]. " 不,你不能用Java中的接口做你想做的事。[你必须用类来做)。

There is one thing that you missed: 你错过了一件事:

Therefore (unless I've misunderstood something) the original idiom doesn't really buy anything more compared to the far less dramatic: 因此(除非我误解了一些东西)原始成语并没有真正购买任何东西,而不是那么戏剧化:

public interface IComparable<T>

The original idiom does buy you something. 原来成语 买你的东西。 It enforces that the compared object must implement IComparable . 它强制比较的对象必须实现IComparable The less dramatic example would allow you to compare implementing classes to any object without restriction. 不那么引人注目的例子允许您无限制地将实现类与任何对象进行比较。 So... The compiler would allow you to specify Long , or InputStream , or LinkedHashSet<Byte[]> , or anything at all as a type parameter. 所以......编译器允许你指定Long ,或InputStream ,或LinkedHashSet<Byte[]> ,或者任何东西作为类型参数。

When you look at it that way, it's easy to see why this idiom is so common. 当你这样看时,很容易理解为什么这个成语如此常见。

Therefore (unless I've misunderstood something) the original idiom doesn't really buy anything more compared to the far less dramatic: 因此(除非我误解了一些东西)原始成语并没有真正购买任何东西,而不是那么戏剧化:

It does buy something, but it's a different thing than what you're thinking of. 它确实买了东西,但它与你想到的不同。 And when someone writes that, 99.9% of the time it is not what they are trying to buy. 当有人写道时,99.9%的时间并不是他们想买的东西。

So, is there a way to actually declare an interface such that whatever class declares to implement it has a method to compare with objects of its own class, without any loopholes such the one above? 那么,有没有办法实际声明一个接口,以便任何类声明实现它有一个方法来与它自己的类的对象进行比较,没有任何漏洞,如上所述?

No. Because it's not useful in terms of type safety . 不。因为它在类型安全方面没有用。 There's nothing wrong with the public class Foo implements IComparable<A> -- it's perfectly type safe . public class Foo implements IComparable<A>没有任何问题public class Foo implements IComparable<A> - 它是完全类型安全的 If someone wants to make a Foo that can safely compare to A in some way, then that's great. 如果有人想要以某种方式制作一个可以安全地与A比较的Foo ,那就太棒了。 I agree with jahroy'a answer -- it's not a "loophole"; 我同意jahroy的回答 - 这不是“漏洞”; it's a feature. 这是一个功能。 Why not make it more general, as long as it's safe? 为什么使它更通用,只要它是安全的? It doesn't get in the way of anything you're doing. 它不会影响你正在做的任何事情。 If you want to make all your classes compare to themselves, that's fine too. 如果你想让你所有的课程与自己比较,那也没关系。 Everything is fine, as long as it's type safe. 一切都很好,只要它的类型安全。

The only place where you should care about the relationship about a type and the type parameter with which it implements IComparable is where you use it , because that place may legitimately have a need for such a relationship. 你应该关心它实现IComparable的类型和类型参数之间关系的唯一地方是你使用它的地方,因为那个地方可能合法地需要这种关系。 So in that place (a generic class or generic method which is parameterized by a comparable type), we can easily bound the type variable that represents the comparable type like this: T extends IComparable<? super T> 因此,在那个地方(通过可比类型参数化的泛型类或泛型方法),我们可以很容易地绑定代表类似类型的类型变量,如下所示: T extends IComparable<? super T> T extends IComparable<? super T> , allowing us to guarantee that T can compare to itself. T extends IComparable<? super T> ,让我们保证T可以与自己比较。

Don't use generics: 不要使用泛型:

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

Indeed. 确实。 I'd advocate that we use This as the conventional name for such type parameters 我主张我们使用This作为此类型参数的常规名称

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

my previous answer: Convenient way to write generic interface that points out to its implementor 我之前的回答: 编写指向其实现者的通用接口的便捷方式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM