Java 与子级共享基类型列表

Java 与子级共享基类型列表,java,oop,Java,Oop,我有一个基类ShapeManager,其中包含我想要创建的形状列表 enumerate()。然后有一个专门化ColoredShapeManager,它需要 要处理专用的ColoredShapes而不是Shapes: +----------------+ +-------------------------------------+ | Shape | | ShapeManager | |-------------

我有一个基类
ShapeManager
,其中包含我想要创建的形状列表
enumerate()
。然后有一个专门化
ColoredShapeManager
,它需要 要处理专用的
ColoredShape
s而不是
Shape
s:

+----------------+      +-------------------------------------+
| Shape          |      | ShapeManager                        |
|----------------|      |-------------------------------------|
| + id: int      |      | # shapes: List<Shape>               |
|                |      |                                     |
|                |      | + ShapeManager() {                  |
|                |      |     shapes.add(new Shape());        |
|                |      |   }                                 |
|                |      |                                     |
|                |      | + abstract void enumerate() {       |
|                |      |     for (Shape s: shapes) {         |
|                |      |        // use s                     |
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
         ^                              ^
         |                              |
         +                              +
+----------------+      +-------------------------------------+
| ColoredShape   |      | ColoredShapeManager                 |
|----------------|      |-------------------------------------|
| + color: int   |      | + ColoredShapeManager() {           |
|                |      |     shapes.add(new ColoredShape()); |
|                |      |   }                                 |
|                |      |                                     |
|                |      | + abstract void enumerate() {       |
|                |      |     for (Shape s: shapes) {         |
|                |      |       // use (ColoredShaped) s      |
|                |      |       // will fail for Shapes       |
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
+-------------++-------------------------------------+
|形状| |形状管理器|
|----------------|      |-------------------------------------|
|+id:int | |#形状:列表|
|                |      |                                     |
|| |+ShapeManager(){|
|| |形状。添加(新形状())|
|                |      |   }                                 |
|                |      |                                     |
|| |+抽象空枚举(){|
|| |对于(形状s:shapes){|
|| |//使用s|
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
^                              ^
|                              |
+                              +
+----------------+      +-------------------------------------+
|彩色形状| |彩色形状管理器|
|----------------|      |-------------------------------------|
|+color:int | |+ColoredShapeManager(){|
|| | shape.add(新的ColoredShape())|
|                |      |   }                                 |
|                |      |                                     |
|| |+抽象空枚举(){|
|| |对于(形状s:shapes){|
|| |//使用(彩色形状)s|
|| |//对于形状将失败|
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+
我不确定ShapeManager是否应该与其管理员共享
shapes:List
这似乎有缺陷,因为
ColoredShapeManager.enumerate()
希望 处理
ColoredShape
s。因此,它会铸造元素,但也会铸造一些元素 (由基类添加的)类型为
Shape
,强制转换将失败

即:

  • 这两种类型的形状最终都会出现在列表
    形状中
  • 子管理器中的
    enumerate()
    应该可以访问
    ColoredShape

我是否应该拆分列表并在两位经理中分别创建私有列表?然后enumerate in the child将只在“其”类型的形状上迭代,并在开始/结束时调用父级的
enumerate()

我认为问题在于您正在两个位置构造一个属性-列表形状:一部分在父级,另一部分在子级。这显然不是一个好的设计。你需要改变它。虽然我不能确切地说是如何实现的,但我认为一种解决方案是将列表作为参数提供给构造函数(至少对于父构造函数),而不是在每个构造函数中创建它们。这样,当您使用ColoredShapeManager这样的子类时,您可以构造一个ColoredShapes列表,并从子构造函数中将其传递给父构造函数。这样,在您的所有子方法中,您将只处理彩色Shape。但是,如果您使用的是父类,则只有形状(通过构造函数传递)。

您可以添加形状类型作为管理器类的“类型参数”。因此,基本上,
ColoredShapeManager
可以扩展
ShapeManager
,而这
T
将是内部
列表
数据结构的类型。另外,如果您的
ColoredShapeManager
没有对
ColoredShapes
执行任何特定操作,我认为它甚至不需要新类。但这又取决于你构建应用程序/设计的方式。

访客模式是否适合你

形状

造型经理

abstract void enumerate() {
   for (Shape shape: shapes) {
       shape.doSomething(this);
   }
}
那么您就不需要知道类型,每个形状派生都可以有自己的实现。

为什么不将行为分离出来,并将容器泛化

容器:

public class ShapeManager<T extends Shape> {
    private List<T> shapeList;

    public void processShapes(ShapeProcessor processor){
        for (T shape : shapeList){
            processor.process(shape);
        }
    }
}
或者,进入全文:

公共抽象类形状{
公共无效接受(ShapeProcessor处理器){
处理器。进程(this);
}
}
公共接口形状处理器{
公共空间过程(形状);
公共空隙处理(彩色形状);
}
公共类形状管理器{
私人列表形状列表;
public void processShapes(ShapeProcessor处理器){
用于(形状:形状列表){
形状。接受(处理器);
}
}
}

这允许枚举多种形状,并应用不同类型的处理方法,不同类型的ShapeProcessor也是如此。Manager不关心它们中的任何一个。

您的设计可以工作,但您必须在运行时使用
instanceOf(class)
指令检查形状s是否确实是一个形状,或者它是否是一个彩色形状。如果您开始添加许多不同类型的形状,那么这样做可能会变得混乱。正确的方法是定义每个形状将实现的接口,这样每个形状都可以以相同的方式使用

为什么不使用


公共接口IShape{
公共int枚举();
}




import java.util.List;
公共类ShapeManager实现了IShape{
列表形状;
公共int枚举(){
public class ShapeManager<T extends Shape> {
    private List<T> shapeList;

    public void processShapes(ShapeProcessor processor){
        for (T shape : shapeList){
            processor.process(shape);
        }
    }
}
public class ShapeProcessor {

    public void process(Shape shape) {

    }

    public void process(ColoredShape shape){

    }
}
public abstract class Shape {
    public void accept(ShapeProcessor processor){
        processor.process(this);
    }
}

public interface ShapeProcessor {
    public void process(Shape shape);
    public void process(ColoredShape shape);
}

public class ShapeManager {
    private List<Shape> shapeList;

    public void processShapes(ShapeProcessor processor){
        for (Shape shape : shapeList){
            shape.accept(processor);
        }
    }
}
public class Shape implements IShape {

int id;

public int enumerate() {
    return id;
}

}
public class ShapeColor extends shape {

    int color;

    public int enumerate() {

        return //whatever you need;
    }

}
import java.util.List;

public class ShapeManager implements IShape {

    List<IShape> shapes;

    public int enumerate() {
        for(IShape s : shapes){
            //do stuff
        }
        return 0;
    }

}
+----------------+      +---------------------------------------+        +------------------------------+
| Shape          |      | AbstractShapeManager<S extends Shape> |        | ShapeManager<Shape>          |
|----------------|      |---------------------------------------|        |------------------------------|
| + id: int      |      | # shapes: List<S>                     |        | + Shape() {                  |
|                |      |                                       |        |     shapes.add(new Shape()); |
|                |      | + abstract void enumerate() {         | < —— + |   }                          |
|                |      |     for (S s: shapes) {               |        |                              |
|                |      |        /* use s */                    |        | + void enumerate() {         |
|                |      |     }                                 |        |     for (Shape s: shapes) {  |
|                |      |   }                                   |        |       // use Shape           |
+----------------+      +---------------------------------------+        |     }                        |
         ^                              ^                                |   }                          |
         |                              |                                +------------------------------+
         +                              +
+----------------+      +-------------------------------------+
| ColoredShape   |      | ColoredShapeManager<ColoredShape>   |
|----------------|      |-------------------------------------|
| + color: int   |      | + ColoredShapeManager() {           |
|                |      |     shapes.add(new ColoredShape()); |
|                |      |   }                                 |
|                |      |                                     |
|                |      | + void enumerate() {                |
|                |      |     for (ColoredShape s: shapes) {  |
|                |      |       // use ColoredShape           |
|                |      |     }                               |
|                |      |   }                                 |
+----------------+      +-------------------------------------+