我有以下界面:
public interface ClusterPopulation
{
public double computeDistance(ClusterPopulation other);
}
是否可以在接口本身中指定,ClusterPopulation的实现A只能将A实现作为computeDistance的参数?
我看到的唯一的approching解决方案如下,但我不喜欢它:
使用泛型重新定义界面:
public interface ClusterPopulation
{
public <T extends ClusterPopulation> double computeDistance(T other);
}
在实现中,如果参数不是良好类型,则抛出IllegalArgumentException,如果类型正常,则执行一些强制转换... Meeeeh!
即使采用这种方法,最终用户也只是通过阅读文档/查看代码实现/试验和错误来了解约束...
有更好的解决方案吗?
答案 0 :(得分:5)
您对使用泛型有正确的想法,但不是将其应用于方法,而是将其应用于整个界面。
public interface ClusterPopulation<T extends ClusterPopulation<T>>
{
double computeDistance(T other);
}
这允许实现将T
定义为自身。
public class ClusterPopulationA implements ClusterPopulation<ClusterPopulationA> { // ...
但是,它并不禁止实现将其定义为其他内容。
public class BreaksPattern implements ClusterPopulation<ClusterPopulationA>
在您的文档中包含所有子类应将类型参数T
定义为自己的类。
答案 1 :(得分:0)
在我看来,您的设计存在一个导致问题的缺陷。根据您提供的内容,似乎ClusterPopulation应该是一个类,而不是一个接口。让我们看看这个方法,
public double computeDistance(ClusterPopulation other);
这是什么意思?这意味着将ClusterPopulation类型的对象传递给此方法。此外,此对象必须具有一些属性,否则如果不是这样,您将如何计算与该对象的距离?结合这两个观察结果,可以得出结论,ClusterPopulation应该是一个类,以便拥有该类型的对象。当我说一堂课时,它可以是具体的或抽象的。让我们以抽象类为例。
public abstract class ClusterPopulation
{
// common attributes, if any
abstract public double computeDistance();
}
public class A extends ClusterPopulation {
public double computeDistance() {
// do some computation based on ClusterPopulation attributes
}
}
public class B extends ClusterPopulation {
public double computeDistance() {
// do computation based on ClusterPopulation attributes
}
}
现在,您可以这样使用它:
ClusterPopulation a = new A();
ClusterPopulation b = new B();
double aResult = a.computeDistance();
double bResult = b.computeDistance();
请注意,此处强制执行您所需的限制。虽然 a 和 b 都是ClusterPopulation类型的对象,但 computeDistance()仅适用于调用对象的具体类型。