c# - 如何在基类中初始化应该在子类中初始化的字段?

标签 c# oop

我的基类 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();
    }

}

如何更好的初始化引擎?

Version 1. Field 保证被初始化但是有很多字段构造函数看起来很难看。没有错误但丑陋。

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

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

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

所以每个版本都有利有弊。哪个版本更好?或者您甚至可以提出其他建议。

最佳答案

版本 3 是对 Template method design pattern 的一种改造.如果你的基类不能提供一个合理的默认实现,但你又要求每辆车都有一个引擎,那么将创建委托(delegate)给基类是一个非常合适和安全的解决方案。我会稍微调整你的初始化是这样的:

protected abstract Engine InitializeEngine();

然后在 Car 的构造函数中:

public Car() {
    engine = InitializeEngine();
}

这将使契约(Contract)非常明确。您的子类只需要提供一个引擎,您的基类将保证在调用构造函数后分配引擎变量。

关于c# - 如何在基类中初始化应该在子类中初始化的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14314966/

相关文章:

c# - System.Threading.TimerCallback 仅在使用 Entity Framework 时触发一次

c# - C#中通过OLEDB导入CSV文件时如何指定分隔符

c# - 作为服务定位器的通用静态类

c++ - Haskell 中的面向对象编程

javascript - ES6 类 - 更新静态属性

c# - 在静态构造函数中初始化静态变量而不是直接赋值有什么好处

c# - 当另一个类只知道父类(super class)时,如何访问子类?

c# - 如何在 DockPanel (WPF) 中的对象之间创建垂直空间?

c# - 避免在数字上下对话框中按 enter 时发出蜂鸣声

c# - 从日期 vb.net 计算耗时?