java - 对于这个简单的层次结构 Java 问题,我的最佳方法是什么?

标签 java generics subclass superclass

首先,我对问题标题感到抱歉,但我想不出更好的标题来描述我的问题。请随意更改它:)

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

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

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

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

要知道的另一件重要的事情是,对于创建的每个框,无论是 BoxA 还是 BoxB,每个 Shape 列表都完全相同。假设我创建了一个名为 lsSquare 列表和两个名为 boxA1BoxA 对象框A2。无论如何,boxA1boxA2 必须具有相同的 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));
    }
}

由于该类型的对象的列表需要相同,因此我将其声明为静态,并且使用该列表的所有方法也是静态。现在,对于 BoxB ,该类在列表内容方面几乎是相同的。我只需将 Square 替换为 Triangle 即可解决问题。因此,对于创建的每个 BoxA 对象,该列表将只有一个且相同。对于创建的每个 BoxB 对象也会发生同样的情况,但当然具有不同类型的列表。

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

我想不出在父类(super class) Box 中执行此操作的方法。尝试静态地执行此操作,使用 Shape 而不是 SquareTriangle 是行不通的,因为该列表对于所有 code>BoxABoxB 对象,我需要它只有一个,但对于 Box 的每个子类。

我怎样才能以不同的方式做得更好?

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

最佳答案

你可以尝试这样的事情:

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

get()set() 方法使用 new BoxA() (或 new BoxB() >) 允许访问静态列表,同时还将类型参数传递给父级。由于列表是静态的,所以哪个实例返回它并不重要。常见的方法有它们自己的类型参数,而不是类的类型参数;事实上,您可以从 BoxA 内部调用 getCommon(new BoxB()),因此您的工作就是确保调用正确的函数。

关于java - 对于这个简单的层次结构 Java 问题,我的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2923860/

相关文章:

c# - 重构为子类

c++ - 非标量类型子类错误

java - 如何在 java/groovy 中模拟方法?

java - Dagger2 找不到带注释的方法

java - 项目转换为maven后JSP类未定义类型

java - 如何允许基本自动配置类?当我有两个扩展它时,只有第一个被调用

c# - 奇怪的泛型编译错误

java - Mysql数据库异常

c# - 将 MyClass<TDescendent> 转换为 MyClass<TAncestor>

java - 在Java中按类获取子列表