简体   繁体   English

创建一个抽象方法而不固定其参数类型

[英]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. 我正在尝试实现一个Class结构,在这里我可以创建不同类型的Box-Objects。 These types are: Squares, Circles, Rectangles and Hexagons . 这些类型是: 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. 对于抽象的父class Box我想指定一个setDimensions()方法,该方法必须在所有子对象中实现。

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 . CirclesdiameterRectangleswidth and lengthHexagonsSquares 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. 我正在尝试应用prototype模式,在这里您克隆一个基本的框并根据我想放置在新框中的另一个框设置参数。 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. 另外,也可以选择factory pattern ,但是我要避免写太多工厂类。

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. 限制是您必须知道必须提供哪些参数,如果输入错误,则会在运行时获取IllegalArgumentException而不是编译器错误。

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: 在Box类的子类中,您可以执行以下操作:

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

    }

}

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. 然后,您可以让setDimensions方法仅将Dimensions作为参数。

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); 听起来像它属于子类: Circle.setRadius(double r); , Rectangle.setWidth(double w) , Rectangle.setHeight(double h) etc. Rectangle.setWidth(double w)Rectangle.setHeight(double h)等。

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. Square (或Diamond ?)可以扩展Rectangle,并通过调用另一个方法来覆盖这两个方法,以确保边保持相等。

I agree with Dima and dasblinkenlight that it doesn't look like setDimensions belongs to Box . 我同意Dimadasblinkenlight的观点 ,即setDimensions并不属于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 . 编辑 :使用泛型的好处是您可以专用于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, eg, setDimensions(CircleDimension dimensions) . 请注意,如果您定义的类层次结构顶部带有抽象类Dimension ,则无法使用协变参数类型覆盖setDimensions(Dimension dimensions) ,即,您不能将其重写为例如setDimensions(CircleDimension dimensions)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM