Reputation: 2600
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:
instanceof
It should be a nice object-oriented design solution.
Upvotes: 2
Views: 611
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
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
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
Reputation: 187
How about adding getRadius
to Figure, and then throw an UnsupportedOperationException
in the implementation of square?
Upvotes: 1