在这个简单的层次结构Java问题上,我最好的方法是什么?

时间:2010-05-27 18:36:15

标签: java generics subclass superclass

首先,我很抱歉问题标题,但我想不出更好的方法来描述我的问题。随意改变它:)

假设我有这个抽象类Box,它在一些私有变量上实现了几个构造函数,方法和其他东西。然后我有几个子类,如BoxABoxB。这两个都实现了额外的东西。

现在我有另一个抽象类Shape和一些子类,如SquareCircle

对于BoxABoxB,我需要有Shape个对象的列表,但我需要确保只有Square个对象进入BoxA列表中只有Circle个对象进入BoxB列表。

对于该列表(在每个方框中),我需要使用get()set()方法以及addShape()removeShape()方法。

要知道的另一件重要事情是,对于每个创建的框,BoxABoxB,每个Shape列表都完全相同。假设我创建了一个名为Square的{​​{1}}列表和一个名为lsBoxA的{​​{1}}个对象列表。无论如何,boxA1boxA2都必须具有相同的boxA1列表。

这是我的想法:

boxA2

由于该类型的对象的列表需要相同,我将其声明为ls,并且与该列表一起使用的所有方法也是public abstract class Box { // private instance variables public Box() { // constructor stuff } // public instance methods } public class BoxA extends Box { // private instance variables private static List<Shape> list; public BoxA() { // constructor stuff } // public instance methods public static List<Square> getList() { List<Square> aux = new ArrayList<Square>(); for(Square s : list.values()) { aux.add(s.clone()); // I know what I'm doing with this clone, don't worry about it } return aux; } public static void setList(List<Square> newList) { list = new ArrayList<Square>(newList); } public static void addShape(Square s) { list.add(s); } public static void removeShape(Square s) { list.remove(list.indexOf(s)); } } 。现在,对于static,对于列表内容,类几乎是相同的。我只会将static替换为BoxB,问题就解决了。因此,对于创建的每个Square对象,列表将只有一个且相同。对于每个创建的Triangle对象都会发生相同的情况,但当然会使用不同类型的列表。

那么,你问我的问题是什么?好吧,我不喜欢代码... BoxABoxBgetList()setList()方法基本上重复了addShape()和{{1 ,只有列表将容纳的对象的类型是不同的。我想以某种方式避免所有这些方法“重复”。

我想不出在超类removeShape()中这样做的方法。尝试使用BoxA代替BoxBBox进行静态处理也行不通,因为列表只适用于所有ShapeSquare }对象,我需要它只有一个,但是Triangle的每个子类。

我怎么能以不同的方式更好地做到这一点?

PS:我无法描述我的真实例子,因为我不知道我正在做的事情的英文正确的单词,所以我只使用了一个盒子和形状的例子,但它基本相同。

1 个答案:

答案 0 :(得分:1)

您可以尝试以下方式:

abstract class Box<E extends Shape> {

    abstract protected List<E> getList();

    abstract protected void setList(List<E> list);

    protected static <T extends Shape> List<T> getCommon(Box<T> box) {
        List<T> aux = new ArrayList<T>();
        for (T s : box.getList()) {
            aux.add((T) s.clone());
        }
        return aux;
    }

    protected static <T extends Shape> void setCommon(Box<T> box, List<T> newList) {
        // do something on newList here if needed as common functionality
        box.setList(new ArrayList<T>(newList));
    }
}
class BoxA extends Box<Square> {
    private static List<Square> list;

    @Override
    protected List<Square> getList() {
        return list;
    }

    @Override
    protected void setList(List<Square> list) {
        this.list = list;
    }

    public static List<Square> get() {
        return getCommon(new BoxA());
    }

    public static void set(List<Square> newList) {
        setCommon(new BoxA(), newList);
    }
}

它有点hackish但它允许您使用父类来保存一些常用功能。您仍然必须在子类中使用最终方法,但是您在其中所做的只是调用父方法,为它们提供当前类的新实例,以便父方法可以从中推断泛型类型。请注意,getList()setList()不是静态的,以允许它们具有Box的类型参数,并且它们受到保护,因此它们在外部不可见。它们充当私有静态变量(每个扩展类应该具有)的getter setter,以允许访问父级以对属于子级的变量执行常见工作。

get()set()方法使用new BoxA()(或new BoxB())来允许访问静态列表,同时还将type参数传递给父级。由于列表是静态的,因此返回它的实例无关紧要。常用方法有自己的类型参数,而不是类所具有的类型参数;事实上你可以从BoxA内部拨打getCommon(new BoxB()),所以你的工作就是确保你拨打正确的电话。