user1868607
user1868607

Reputation: 2600

Managing different objects in an heterogeneous Java array

I have to solve this "container problem" in Java. I have an array made up with different figures and I'd like the following code to work:

 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();          
            }        
    }
}

Where you can see there is a problem because Square hasn't got a getRadius() method. I have the following restrictions:

It should be a nice object-oriented design solution.

Upvotes: 2

Views: 611

Answers (4)

MockerTim
MockerTim

Reputation: 2483

If you can't use the instanceof you can declare abstract method in the Figure class and add dummy implementation for figures that doesn't need it. The following code without instanceof and java generics works:

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();
        }        
    }
}

Upvotes: 0

Shar1er80
Shar1er80

Reputation: 9041

Why don't you add an enum FigureType to your base class that identifies the child class?

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;
    }
}

You would have to add a default constructor to each child class that calls the parent class constructor with its 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;
    }
}

Usage:

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();
        }
    }
}

Results:

Circle
Circle
Square

No exception

Upvotes: 1

Benjy Kessler
Benjy Kessler

Reputation: 7616

You want to write code that works for all types of Figures and you want different behavior if the Figure is a Circle or Square. This is why they invented polymorphism. Your code looks like:

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

Instead the better way to do this is as follows:

interface Figure {
  public void do();
}

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

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

Then your code becomes:

Figure f;
f.do();

Upvotes: 0

faerubin
faerubin

Reputation: 187

How about adding getRadius to Figure, and then throw an UnsupportedOperationException in the implementation of square?

Upvotes: 1

Related Questions