My base class Car contains an engine field that cannot be initialized in the base class. I can only initialize it in a subclass, for example, in ElectricCar I can write engine = new ElectricEngine . However, I use the field in the base class. Therefore, I have a field that was used but was not initialized:
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(); } }
What is the best way to initialize the engine?
Version 1. Field guaranteed initialization, but with many field constructors will look ugly. No mistakes, but ugly.
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()) { } }
Version 2. Subclasses should remember the initialization of the field, the presence of such a βcontractβ with subclasses can lead to errors (uninitialized field).
public class Car { protected Engine engine; public Car() { } public void Start() { engine.Start();
Version 3. The field must be initialized. The constructor is clear. But calling the virtual method from the constructor (potentially dangerous, not recommended at all).
public class Car { protected Engine engine; public Car() { InitializeEngine(); } protected abstract void InitializeEngine(); public void Start() { engine.Start();
Therefore, each version has pros and cons. Which version is better? Or perhaps you can even offer something else.
source share