【问题标题】:Managing different objects in an heterogeneous Java array管理异构 Java 数组中的不同对象
【发布时间】:2015-08-06 12:23:24
【问题描述】:

我必须用 Java 解决这个“容器问题”。我有一个由不同数字组成的数组,我希望下面的代码可以工作:

 package container;
    class Figure{
        public void draw() {}
        public String getColor() { return null; }
    }

    class Square extends Figure{
        @Override
        public void draw(){
            System.out.println("Square");
        }
    }

    class Circle extends Figure{
        @Override
        public void draw(){
            System.out.println("Circle");
        }
        public float getRadius(){
            return 8;
        }
    }

    public class Container {

        public static void main(String[] args) {

            Figure[] figures = new Figure[3];
            figures[0]= new Circle();
            figures[1]= new Circle();
            figures[2]= new Square();

            for(Figure figure:figures){
                figure.getColor();
                figure.draw(); 
                ((Circle) figure).getRadius();          
            }        
    }
}

在哪里可以看到有问题,因为Square 没有getRadius() 方法。我有以下限制:

  • 不能使用泛型
  • 不能使用instanceof

它应该是一个不错的面向对象的设计解决方案。

【问题讨论】:

  • 预期的行为是什么? Square 不是圆形 - 那条线应该如何工作?

标签: java arrays polymorphism containers heterogeneous


【解决方案1】:

为什么不将enum FigureType 添加到标识子类的基类中?

public static enum FigureType {

    Square,
    Circle
}

public static class Figure {
    private FigureType type;

    public Figure(FigureType type) {
        this.type = type;
    }

    public FigureType getType() {
        return type;
    }

    public void draw() {
    }

    public String getColor() {
        return null;
    }
}

您必须为每个使用其FigureType 调用父类构造函数的子类添加一个默认构造函数。

public static class Square extends Figure {

    public Square() {
        super(FigureType.Square);
    }

    @Override
    public void draw() {
        System.out.println("Square");
    }
}

public static class Circle extends Figure {

    public Circle() {
        super(FigureType.Circle);
    }

    @Override
    public void draw() {
        System.out.println("Circle");
    }

    public float getRadius() {
        return 8;
    }
}

用法:

public static void main(String[] args) {

    Figure[] figures = new Figure[3];
    figures[0] = new Circle();
    figures[1] = new Circle();
    figures[2] = new Square();

    for (Figure figure : figures) {
        figure.getColor();
        figure.draw();
        if (figure.getType() == FigureType.Circle) {
            ((Circle) figure).getRadius();
        }
    }
}

结果:

Circle
Circle
Square

没有例外

【讨论】:

    【解决方案2】:

    getRadius添加到Figure,然后在square的实现中抛出一个UnsupportedOperationException怎么样?

    【讨论】:

      【解决方案3】:

      您可以尝试使用 try/catch 来防止 ClassCastException:

      try {
         ((Circle) figure).getRadius();
      } catch(ClassCastException e) { 
          //does nothing 
      } 
      

      【讨论】:

        【解决方案4】:

        您想要编写适用于所有类型的Figures 的代码,并且如果FigureCircleSquare,您想要不同的行为。这就是他们发明多态性的原因。您的代码如下所示:

        Figure f;
        if (f is Circle) {
          doFoo();
        } else {
          doBar();
        }
        

        相反,更好的方法如下:

        interface Figure {
          public void do();
        }
        
        class Circle implements Figure {
          public void do() {
            doFoo();
          }
        }
        
        class Square implements Figure {
          public void do() {
            doBar();
          }
        }
        

        那么你的代码就变成了:

        Figure f;
        f.do();
        

        【讨论】:

        • 这是对的,但是如果圆有一些行为(getRadious)它不存在于正方形和图形中怎么办?
        • 那就不要暴露给用户了。为什么用户需要半径。
        • 用户可能正在尝试执行一些与Figures 相关的操作,我将此操作称为do
        【解决方案5】:

        如果您不能使用instanceof,您可以在Figure 类中声明抽象方法,并为不需要它的图形添加虚拟实现。以下没有instanceof 和java泛型的代码有效:

        package container;
        
        abstract class Figure {
            public void draw(){};
            public String getColor(){return null;};
        
            protected abstract float getRadius();
        }
        
        class Square extends Figure{
            @Override
            public void draw(){
                System.out.println("Square");
            }
        
            // zero radius for non-circle figures, for instance
            // or you can throw UnsupportedOperationException here.
            public float getRadius() { return 0;} 
        }
        
        class Circle extends Figure{
            @Override
            public void draw(){
                System.out.println("Circle");
            }
            public float getRadius(){
                return 8;
            }
        }
        
        public class Container {
        
            public static void main(String[] args) {
        
                Figure[] figures = new Figure[3];
                figures[0]= new Circle();
                figures[1]= new Circle();
                figures[2]= new Square();
        
                for(Figure figure:figures){
                    figure.getColor();
                    figure.draw(); 
        
                    figure.getRadius();
                }        
            }
        }
        

        【讨论】:

        • 我知道这会很完美,但我被限制“不能使用 instanceof”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-01
        • 1970-01-01
        • 2016-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多