我的基类Car包含engine无法在基类中初始化的字段.我只能在子类中初始化它,例如ElectricCar我可以编写engine = new ElectricEngine.但是我在基类中使用了字段.所以我有一个使用但未初始化的字段:
public class Car {
protected Engine engine;
public void Start() {
engine.Start();
// do something else
}
public void Stop {
engine.Stop();
// do something else
}
public void Diagnose() {
engine.Diagnose();
// anotherField.Diagnose();
// oneAnotherField.Diagnose();
}
}
Run Code Online (Sandbox Code Playgroud)
如何更好地初始化引擎?
版本1.字段保证初始化但有许多字段构造函数看起来很难看.没有错误,但很难看.
public class Car {
protected Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void Start() {
engine.Start();
// do something else
}
public void Stop {
engine.Stop();
// do something else
}
public void Diagnose() {
engine.Diagnose();
// anotherField.Diagnose();
// oneAnotherField.Diagnose();
}
}
public class ElectricCar : Car {
public ElectricCar() : base (new ElectricEngine()) {
}
}
Run Code Online (Sandbox Code Playgroud)
版本2.子类应该记住初始化字段,与子类的这种"契约"可能会引入错误(未初始化的字段).
public class Car {
protected Engine engine;
public Car() {
}
public void Start() {
engine.Start();
// do something else
}
public void Stop {
engine.Stop();
// do something else
}
public void Diagnose() {
engine.Diagnose();
// anotherField.Diagnose();
// oneAnotherField.Diagnose();
}
}
public class ElectricCar : Car {
public ElectricCar() {
engine = new ElectricEngine();
}
}
Run Code Online (Sandbox Code Playgroud)
版本3.保证初始化字段.构造函数很清楚.但是从构造函数调用虚方法(有潜在危险,一般不推荐).
public class Car {
protected Engine engine;
public Car() {
InitializeEngine();
}
protected abstract void InitializeEngine();
public void Start() {
engine.Start();
// do something else
}
public void Stop {
engine.Stop();
// do something else
}
public void Diagnose() {
engine.Diagnose();
// anotherField.Diagnose();
// oneAnotherField.Diagnose();
}
}
public class ElectricCar : Car {
public ElectricCar() {
}
protected void override InitializeEngine() {
engine = new ElectricEngine();
}
}
Run Code Online (Sandbox Code Playgroud)
所以每个版本都有优点和缺点.哪个版本更好?或者你甚至可以建议别的东西.
版本3是对模板方法设计模式的一种看法.如果你的基类不能提供合理的默认实现,但是你需要每辆车都有一个引擎,那么将创建委托给基类是一个非常合适和安全的解决方案.我会稍微调整你的初始化,如下所示:
protected abstract Engine InitializeEngine();
Run Code Online (Sandbox Code Playgroud)
然后在你的Car构造函数中:
public Car() {
engine = InitializeEngine();
}
Run Code Online (Sandbox Code Playgroud)
这将使合同非常明确.您的子类只需要提供引擎,您的基类将保证在调用构造函数后分配引擎变量.
| 归档时间: |
|
| 查看次数: |
1895 次 |
| 最近记录: |