扩展对象并继承所有变量

时间:2010-07-18 13:49:17

标签: java inheritance

假设我有一个类Car的对象,有30个变量,从最高速度到颜色。我想创建一个MyCar对象(类MyCar扩展Car),它基本上是相同的东西,除了它存储更多的信息。

我不可能立即创建MyCar对象(因为在数千个Car对象中只有少数会成为MyCar对象),除非我将其他字段留空,但这似乎不太专业。也没有创建一个带有30个参数的构造函数,或者通过方法调用设置30个参数。

那么,有没有办法轻松地从超类对象继承所有变量?

PS:我的计划不是关于汽车,但我认为这将是一个更容易的例子。

修改

感谢您的回复。它们对我的程序都有帮助,但不适用于这个特殊问题。建造者似乎没有益处,因为我的这些车没有变量的默认值。每次制造汽车时,所有变量都被填写(这是构建一种“事实表”所需的。)

信封是一个有趣的设计,但仍然要求我复制子类构造函数中的所有变量。我希望有办法绕过这个。模板还需要我逐个复制所有变量。

在我的程序中,子类在搜索引擎中充当一种“包装类”。子类与普通汽车相同,但它们具有“排名分数”。我的程序旨在显示常规汽车,通过扩展它们,我可以轻松地显示子类并同时按分数对它们进行排序。

无论如何我必须创建新对象,因为可以在同一辆汽车列表上执行多次搜索。因此,在原车中编辑变量不是一种选择。

也许这个问题有更好的解决方案,但是现在我想我必须将超类对象传递给构造函数并复制所有变量。

感谢您的帮助!

PS:我只是想,也许我可以将所有变量都抛到HashMap中。这样我可以使用.get(varname)访问它们,我只需要将一个HashMap变量传递给子类。下行是我必须投入很多,因为vars是字符串,整数,双打等的混合物。你怎么看,它是否可以接受编码风格?

7 个答案:

答案 0 :(得分:4)

有效的Java第2版,第2项:面对许多构造函数参数时考虑构建器

  

也没有创造   带有30个参数的构造函数,   或通过方法设置30个参数   调用

如果您正面对参数太多的构造函数,那么您可能需要查看:Builder Pattern。 我们的想法是只将您想要/知道的字段设置到构建器中,而不必使用可选,或者您想要使用默认值值,然后调用build()来构造实际对象。请参阅该文章中的Java示例。

一旦你设置了那个模式,就可以用这种方式构建Cars(注意干净的结构):

Car car = new Car.Builder(required_param1, required_param2)
                 .color(RED) // optional params
                 .topSpeed(300)
                 .zeroToHundred(2)
                 .build();

答案 1 :(得分:1)

您可以添加一个获取Car对象的构造函数,并将Car中的值复制到新的MyCar。

答案 2 :(得分:1)

  

我不可能立即创建MyCar对象(因为在数千个Car对象中只有少数将成为MyCar对象),

那么,你会有很多Car类型的对象,其中一些你想在运行时“提升”到SpecialCar类型?

SpecialCars与Cars有完全相同的界面吗?

您可能想要阅读Coplien的Envelope-Letter Pattern,这是一种在运行时“更改”对象类型的方法。当然,对象并没有真正改变类型;相反,一个不同的“字母”进入现有的“信封”。信封是其他代码引用的句柄,但信封上的方法调用被委托给信件:

 class CarEnvelope { // an envelope
    Car c ; // the letter
    CarEnvelope( Car c ) { this.c = c ; }
    int someMethod() { 
      return c.someMethod(); // delegate 
    }
    void promoteToSpecialType() {
       if( ! c.isSpecialCar() ) {
          c = new SpecialCar( c ) ;
    }
 }

 class Car {
   Car() {}
   int someMethod() { do Car stuff }
   boolean isSpecial() { return false; }
 }

 class SpecialCar extends Car {
   SpecialCar( Car c ) { /*copy c's attributes...*/ } 
   int someMethod() { do SpecialCar stuff}
   boolean isSpecial() { return true; }
 }

 CarEnvelope c = new CarEnvelope( new Car() ) ;
 // do stuff with c
 c.someMethod(); // indirectly calls Car.someMethod();
 // promote
 c.promoteToSpecialType();
 c.someMethod(); // indirectly calls SpecialCar.someMethod

答案 3 :(得分:1)

OP在这里。

我明白这看起来像是懒惰。但我已经通过在构造函数中手动复制30个变量来实现它。我知道,这不是一件大事。

事情是,我被教会用风格编码。当我看到看起来像copypasta的无意识的代码块时,我的直觉告诉我可能有更好的方法。因此,我学习和追求完美的愿望驱使我来到这里。

但如果没有其他方法可以复制变量(或覆盖所有的get& set方法),那么我不需要再看了。

毋庸置疑,本主题中的所有回复都给了我新的见解。谢谢你们。

答案 4 :(得分:0)

我感觉你所寻找的是模板的概念; e.g。

public class Car {
   private final int attr1;
   private final int attr2;
   ...

   public Car() {
       super();
   }

   /* copy constructor */
   public Car(Car template) {
       this.attr1 = template.attr1;
       this.attr2 = template.attr2;
       ...
   }

   /* setters and getters */
}

然后......

Car myTemplate = new Car();
myTemplate.setAttr1(3);
myTemplate.setAttr2(11);
...

Car car1 = new Car(myTemplate);
car1.setAttr1(4);
Car car2 = new Car(myTemplate);
car1.setAttr1(5);

答案 5 :(得分:0)

我不明白。常规继承有什么问题?

class Car {
    private int attributeOne;
    .....
    private boolean attrbuteThirty;

    public void methodOne(){...}
    ...
    public void methodThirty(){...}
}

然后只是将其分类:

 class SubCar extends Car {
     private int extraAttribute;
  }

所有30多个属性和方法都已经被继承,这就是extends的全部内容。

如果您需要根据现有数据创建对象,则您拒绝代码它! (¬¬),那么你可以创建一个小脚本来为你创建代码。这很容易。您复制/粘贴生成的代码,您就完成了。

如果您不想这样做,因为您不想复制数据,您可以覆盖有趣的方法,并将代码委托给原始代码,这就是Decorator design pattern的全部内容:

class SubCar extends Car {
    private Car wrapped;
    private String extraAttribute;
    public SubCar( Car original, String newAttributeOne ) {
        wrapped = original;
        this.extraAttribute = newAttributeOne;
   }

    public void someMethod() {
        wrapped.someMethod();
    }
    public String getName() { return wrapped.getName();  }
    ... and so on
    // new method 
    public String extraAttribute() { return extraAttribute; }
}

这样你就不会复制数据了,只是装饰它。

答案 6 :(得分:0)

我们可以创建一个接口ICar,它包含所有30列的所有getter和setter。 Car可以实现ICar,并且可以包含所有30个字段及其相应的getter和setter。 MyCar还可以实现ICar并可以使用组合。它将Car的方法暴露为委托方法(可以在像eclipse这样的IDE中自动生成)

public interface ICar {
// getter and setter methods
}

public Car implements ICar {
 private String color;
 // getters and setters for each of the fields
}

public MyCar implements ICar {
 private Car car;
 public MyCar(Car car){
  this.car = car;
 }
 public String getColor() {
  return car.getColor();
 }
}

然后,所有消费者都可以使用ICar界面进行操作。那会有用吗?