0

我确定我会以错误的方式解决这个问题,但是我想实现一个通用模式,其中某个类的实例表示集合的元素,而该类的静态方法将集合的属性指定为整个。我从一个类开始,因此只有一个集合,但我想将它扩展到类似的集合,并拥有适用于所有这些集合的通用方法。我正在考虑创建更多类并让它们都扩展相同的接口,但这将涉及指定静态方法的接口和覆盖它们的实现类。

我认为这个问题可能最好用群论来解释。对于那些不知道的人,组是一个数学对象,它包含一组元素,以及一个组合两个元素并返回第三个元素的组运算(用 * 表示)。在其他条件中,必须有一个单位元素 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 对象之类的代码变得复杂(所有内容都需要两个类型参数,我将不得不重新编写我的很多代码,我不确定如何指定两个接口之间的关系)。此外,我刚刚意识到,在输入这​​个界面时,您必须允许在来自不同组的两个元素之间进行组操作,这没有任何意义。那么,实现这种结构的正确方法是什么?

4

2 回答 2

1

考虑第一句中的子句:“某个类的实例表示集合的元素”。其中包含两个与问题相关的名词,“元素”和“集合”。我最初的想法可能会随着我对这个问题的更多了解而改变,应该有两个类,Element 和 Set。我可能会重命名“Set”以避免与 java.util.Set 混淆——如果这是 Group Theory,“Group”将是一个不错的选择。

如果这样做,则可以将元素相关的方法放在 Element 中,将与集合相关的方法放在 Set 中。两者都可以被子类化,并具有正常的覆盖。

于 2013-01-08T23:14:14.687 回答
1

这里的解决方案——例如它——是从不同的方向看待事物。组应该是与其元素分开的对象,并且组对象应该有一个T operate(T, T)和一个T identity()方法。

换句话说,停止尝试拥有GroupElement接口并拥有Group接口。

此外,泛型可能会简化问题:Group<T>带有 type 的元素T

于 2013-01-08T23:08:01.783 回答