我确定我会以错误的方式解决这个问题,但是我想实现一个通用模式,其中某个类的实例表示集合的元素,而该类的静态方法将集合的属性指定为整个。我从一个类开始,因此只有一个集合,但我想将它扩展到类似的集合,并拥有适用于所有这些集合的通用方法。我正在考虑创建更多类并让它们都扩展相同的接口,但这将涉及指定静态方法的接口和覆盖它们的实现类。
我认为这个问题可能最好用群论来解释。对于那些不知道的人,组是一个数学对象,它包含一组元素,以及一个组合两个元素并返回第三个元素的组运算(用 * 表示)。在其他条件中,必须有一个单位元素 e,使得所有 e 的 a * e = a,并且每个元素 a 必须有一个逆 ai,使得 a * ai = e。最简单的例子是整数,其中加法是群运算,单位元素为零,元素的逆是它的否定。如果我有一个操作组元素的通用类,那么在某些情况下我需要知道组的标识元素是什么。
所以我的群组示例界面可能类似于
public interface GroupElement {
public GroupElement operate(GroupElement element);
public static GroupElement identity();
}
整数实现是这样的(忽略与先前存在的 Integer 类的明显冲突):
public class Integer implements GroupElement {
private int i;
public Integer(int i) {
this.i = i;
}
public Integer operate(Integer other) {
return new Integer(i + other.i);
}
public static Integer identity() {
return new Integer(0);
}
}
然后是一个通用对象,用于检查一个元素是否与另一个元素相反:
public class InverseChecker <E implements GroupElement> {
public boolean isInverse(e element1, e element2) {
return element1.operate(element2).equals(E.identity());
}
}
显然上面的代码有很多错误。第一个问题是我无法在接口中声明静态方法,即使我使用抽象父类,子类也无法覆盖静态方法。我可以使 identity() 方法成为非静态方法,但是我需要它的一个实例,而我并不总是拥有它。我也不能从泛型类型 E 调用静态方法。我想我可以制作两个接口,一个用于组,一个用于组的元素,但是看起来它确实会使 InverseChecker 对象之类的代码变得复杂(所有内容都需要两个类型参数,我将不得不重新编写我的很多代码,我不确定如何指定两个接口之间的关系)。此外,我刚刚意识到,在输入这个界面时,您必须允许在来自不同组的两个元素之间进行组操作,这没有任何意义。那么,实现这种结构的正确方法是什么?