nitowa
nitowa

Reputation: 1107

Create an abstract method without fixing the types of its parameters

I'm trying to implement a Class structure, where I'm able to create Box-Objects of different types. These types are: Squares, Circles, Rectangles and Hexagons.

For the abstract father class Box I'd like to specify a setDimensions() method that has to be implemented in all child objects.

However, the dimension parameters for all objects are different (Except for the height):

Circles have a diameter, Rectangles have a width and length, and Hexagons and Squares have equally sized sides.

Is it possible to define a Interface/abstract method that can handle this type of job?

//EDIT: This is for a programming assignment. Obviously all classes have suitable constructors, but this program "simulates" a project where the implementation of a design pattern is supposed to be useful. I'm trying to apply the prototype pattern, where you clone a basic box and set the parameters based on another box that I would like to place in the new one. I know it isn't a terribly good example, but we have to solve it that way. Alternatively a factory pattern is also an option, but I would like to avoid having to write too many factory classes.

Upvotes: 1

Views: 98

Answers (4)

Kulu Limpa
Kulu Limpa

Reputation: 3541

I agree with Dima and dasblinkenlight that it doesn't look like setDimensions belongs to Box. However - as an alternative answer to the question - there's also a way to achieve this using generics:

abstract public class Box<D> {
    public abstract void setDimensions(D dimensions);
}

class Square extends Box<Double> {
    public void setDimensions(Double dimensions) {/*-*/}
}

class Circle extends Box<Double> {
    public void setDimensions(Double dimensions) {/*-*/}
}

// (say Tuple is a generic container for two elements)
public class Rectangle extends Box<Tuple<Double, Double>> {
    public void setDimensions(Tuple<Double, Double> dimensions) {/*-*/}
}

Edit: The benefit of using generics is that you can specialize the type of the argument of setDimensions. Note that, if you define a class hierachy with an abstract class Dimension on top, you cannot override setDimensions(Dimension dimensions) with a covariant argument type, that is, you cannot override it as, e.g., setDimensions(CircleDimension dimensions).

Upvotes: 0

Predrag Maric
Predrag Maric

Reputation: 24423

Here's my two cents.

You could have something like this in abstract superclass

public abstract void setDimensions(double... dim);

And one sample implementation (rectangle) would be

// expected params are width and height
public void setDimension(double... dim) {
    if (dim.length != 2) {
        throw new IllegalArgumentException("Two dimensions expected, width ang height!");
    }
    ...
}

And you would call it like this

Rectangle rec = new Rectangle();
rec.setDimensions(1.5, 2.8);
// rec.setDimensions(1.0); would throw IllegalArgumentException

Restrictions are that you would have to know what parameters you would have to supply, and if you are wrong you will get IllegalArgumentException in runtime, instead of compiler error.

Upvotes: 1

javaHunter
javaHunter

Reputation: 1097

Here is a small implementation for the classes:

  interface Dimension{
       int getWidth();
       int getLenght();
       int getRadius();
      }

    CircleDimension implements Dimension{
       int radius;
       int getWidth(){
            return -1;
       }
       int getLenght(){
            return -1;
       }
       int getRadius(){
          return radius
       }
   }
    RectangleDimension implements Dimension{
       int width;
       int length;
       int getWidth(){
            return width;
       }
       int getLenght(){
            return length;
       }
       int getRadius(){
          return -1;
       }

class Box{
  void setDimension(Dimension dimension);
}

And in the subclasses of the Box class, you can do:

class Rectangle{
    int length;
    int width;
    setDimension(Dimension dimension){
      if(!dimension.getClass().equals(RectangleDimension)){
             //thow illegal argument exception
      }else{
       length = dimension.getlength();
       width  = dimension.getwidth();
      }

    }

}

Upvotes: 0

Dima
Dima

Reputation: 40500

Well, you could create a parallel class hierarchy for dimensions ...

abstract class Dimensions {}
class Radius extends { double r; }
class WidthHeight extends { double w; double h; }

Then you can have your setDimensions method just take Dimensions as argument.

I am not sure I see a utility of this though: since the notion of "dimension" is vastly different between your concrete classes, there seems to be no use for the superclass method. It sounds like it belongs to the child classes: Circle.setRadius(double r);, Rectangle.setWidth(double w), Rectangle.setHeight(double h) etc.

Square (or Diamond?) could extend Rectangle, and override the two methods by calling the other as well to make sure that the sides remain equal.

Upvotes: 0

Related Questions