简体   繁体   English

我知道在Java中不可能使用抽象/重写的静态方法,但我的代码似乎需要它们

[英]I know abstract/overridden static methods are not possible in Java, but my code seems to require them

I'm sure I'm going about this in the wrong way, but there is a general pattern I want to implement in which instances of a certain class represent elements of a set, and static methods of the class give properties of the set as a whole. 我确定我会以错误的方式解决这个问题,但是我想要实现一种通用模式,其中某个类的实例表示集合的元素,而类的静态方法将集合的属性赋予整个。 I started off with only one class and thus one set, but I want to extend it to similar sets and have generic methods that work for all of them. 我开始时只有一个类,因此有一个集合,但我想将它扩展到类似的集合,并且具有适用于所有类的泛型方法。 I was thinking making more classes and having them all extend the same interface, but this would involve the interface specifying static methods and the implementing classes overriding them. 我正在考虑制作更多类并让它们都扩展相同的接口,但这将涉及指定静态方法的接口和覆盖它们的实现类。

I think the problem might be best explained using Group Theory. 我认为使用群论可以最好地解释问题。 For those who don't know, a group is a mathematical object that comprises a set of elements, along with a group operation (represented by *) that combines two elements and returns a third. 对于那些不知道的人来说,一个组是一个数学对象,它包含一组元素,以及一个组合操作(由*表示),它组合了两个元素并返回第三个元素。 Among other conditions there must be an identity element e such that a * e = a for all e, and every element a must have an inverse ai such that a * ai = e. 在其他条件中,必须存在标识元素e,使得对于所有e,a * e = a,并且每个元素a必须具有逆ai,使得a * ai = e。 The simplest example is the integers where addition is the group operation, the identity element is zero, and the inverse of an element is its negation. 最简单的例子是整数,其中加法是组操作,标识元素是零,元素的倒数是它的否定。 If I have a generic class that manipulates elements of a group, there are instances where I would need to know what the identity element of the group is. 如果我有一个操纵组元素的泛型类,那么有些实例我需要知道组的标识元素是什么。

So my sample interface for groups might be something like 所以我的组的示例界面可能是这样的

public interface GroupElement {

    public GroupElement operate(GroupElement element);

    public static GroupElement identity();

}

With the integer implementation being this (ignore the obvious conflict with the preexisting Integer class): 使用整数实现(忽略与预先存在的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);
    }
}

And then a generic object that checks if one element is the inverse of another: 然后是一个通用对象,检查一个元素是否与另一个元素相反:

public class InverseChecker <E implements GroupElement> {

    public boolean isInverse(e element1, e element2) {
        return element1.operate(element2).equals(E.identity());
    }
}

Obviously there is a lot wrong with the above code. 显然上面的代码有很多错误。 The first problem is that I cannot declare a static method in an interface, and even if I used an abstract parent class the child classes could not override the static method. 第一个问题是我无法在接口中声明静态方法,即使我使用了抽象父类,子类也无法覆盖静态方法。 I could make the identity() method non-static, but then I would require an instance of it which I wouldn't always have. 我可以使identity()方法非静态,但后来我需要一个我不会总是拥有它的实例。 Also I can't call a static method from the generic type E either. 另外,我也不能从泛型类型E调用静态方法。 I suppose I could make two interfaces, one for groups and one for elements of groups, but then it seems like it would really complicate code from something like the InverseChecker object (would need two type parameters for everything and I would have to re-write a lot of my code, and I'm not sure how I would specify the relationship between the two interfaces). 我想我可以创建两个接口,一个用于组,一个用于组的元素,但是它似乎真的会使代码变得复杂,比如InverseChecker对象(对于所有内容都需要两个类型参数,我将不得不重写)很多我的代码,我不知道如何指定两个接口之间的关系)。 Also I just realized when typing this out that the way the interface is constructed you would have to allow group operations between two elements from different groups, which doesn't make sense. 此外,我刚刚意识到,在输入接口的方式时,你必须允许来自不同组的两个元素之间的组操作,这没有意义。 So, what is the correct way to implement this kind of structure? 那么,实现这种结构的正确方法是什么?

The solution here -- such as it is -- is to look at things in a different direction. 这里的解决方案 - 例如它 - 是以不同的方向看待事物。 The group should be a separate object from its elements, and the group object should have a T operate(T, T) and a T identity() method. 该组应该是与其元素分开的对象,并且组对象应该具有T operate(T, T)T identity()方法。

In other words, stop trying to have a GroupElement interface and have a Group interface. 换句话说,停止尝试拥有GroupElement接口并具有Group接口。

Also, generics would probably simplify matters: a Group<T> with elements of type T . 此外,泛型可能会简化事项:一Group<T>与类型的元素T

Consider the clause in the first sentence: "instances of a certain class represent elements of a set". 考虑第一句中的子句:“某个类的实例表示集合的元素”。 That contains two problem-related nouns, "element" and "set". 它包含两个与问题相关的名词,“元素”和“集合”。 My initial thinking, subject to change as I learn more about the problem, would be to have two classes, Element and Set. 我最初的想法,随着我对问题的更多了解而变化,将有两个类,元素和集合。 I might rename "Set" to avoid confusion with java.util.Set - if this is Group Theory, "Group" would be a good alternative. 我可能会重命名“Set”以避免与java.util.Set混淆 - 如果这是Group Theory,“Group”将是一个不错的选择。

If you do that, you can put element related methods in Element, and set-related methods in Set. 如果这样做,您可以在Element中放置与元素相关的方法,在Set中放置与set相关的方法。 Both can be subclassed, with normal overriding. 两者都可以是子类,具有正常的覆盖。

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

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