假设我有一个类Car的对象,有30个变量,从最高速度到颜色。我想创建一个MyCar对象(类MyCar扩展Car),它基本上是相同的东西,除了它存储更多的信息。
我不可能立即创建MyCar对象(因为在数千个Car对象中只有少数会成为MyCar对象),除非我将其他字段留空,但这似乎不太专业。也没有创建一个带有30个参数的构造函数,或者通过方法调用设置30个参数。
那么,有没有办法轻松地从超类对象继承所有变量?
PS:我的计划不是关于汽车,但我认为这将是一个更容易的例子。修改
感谢您的回复。它们对我的程序都有帮助,但不适用于这个特殊问题。建造者似乎没有益处,因为我的这些车没有变量的默认值。每次制造汽车时,所有变量都被填写(这是构建一种“事实表”所需的。)
信封是一个有趣的设计,但仍然要求我复制子类构造函数中的所有变量。我希望有办法绕过这个。模板还需要我逐个复制所有变量。
在我的程序中,子类在搜索引擎中充当一种“包装类”。子类与普通汽车相同,但它们具有“排名分数”。我的程序旨在显示常规汽车,通过扩展它们,我可以轻松地显示子类并同时按分数对它们进行排序。
无论如何我必须创建新对象,因为可以在同一辆汽车列表上执行多次搜索。因此,在原车中编辑变量不是一种选择。
也许这个问题有更好的解决方案,但是现在我想我必须将超类对象传递给构造函数并复制所有变量。
感谢您的帮助!
PS:我只是想,也许我可以将所有变量都抛到HashMap中。这样我可以使用.get(varname)访问它们,我只需要将一个HashMap变量传递给子类。下行是我必须投入很多,因为vars是字符串,整数,双打等的混合物。你怎么看,它是否可以接受编码风格?答案 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)
我明白这看起来像是懒惰。但我已经通过在构造函数中手动复制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界面进行操作。那会有用吗?