【问题标题】:c# inherited class initializationc#继承类初始化
【发布时间】:2009-11-20 02:23:07
【问题描述】:

所以我有这门课

public class Options
    {
        public bool show { get; set; }
        public int lineWidth { get; set; }
        public bool fill { get; set; }
        public Color fillColour { get; set; }
        public string options { get; set; }

        public virtual void createOptions()
        {
            options += "show: " + show.ToString().ToLower();
            options += ", lineWidth: " + lineWidth;
            options += ", fill: " + fill.ToString().ToLower();
            options += ", fillColor: " + (fillColour != Color.Empty ? ColourToHex(fillColour) : "null");
        }

        public Options(bool _show, int _lineWidth, bool _fill, Color _fillColour)
        {
            show = _show;
            lineWidth = _lineWidth;
            fill = _fill;
            fillColour = _fillColour;

            createOptions();
        }
}

以及另一个继承它的类

public class Line : Options
    {
        public static bool steps { get; set; }

        public override void createOptions()
        {
            options += ", lines: {";
            options += " steps: " + steps.ToString().ToLower() + ",";
            base.createOptions();
            options += "}";
        }

        public Line(bool _show, int _lineWidth, bool _fill, Color _fillColour, bool _steps)
            : base(_show, _lineWidth, _fill, _fillColour) { steps = _steps; }
    }

当调用对象Line(true, 1, true, Color.Gray, true) 时,它首先覆盖继承的类函数,然后将steps 设置为true

我希望 steps 包含在覆盖中,因此 steps 现在将是 true 而不是 false(其默认值)。

如果可能的话,请给我一些关于如何解决这个问题的指示和提示,并向我解释为什么我的设置不允许在构造函数初始化之后发生覆盖。

【问题讨论】:

  • 此代码无法编译。您从 createOptions 调用“createTypeOptions”但基础没有功能,并且基础没有采用 4 个参数的构造函数。
  • 抱歉,当我将代码复制到 stackoverflow 时,createTypeOptions 应该是 createOptions,我一定错过了。也忘记了选项构造函数
  • 是否有任何理由将步骤设置为静态?

标签: c# inheritance overriding virtual-functions


【解决方案1】:

我想你忘了给我们看 Options 类构造函数,但我猜它调用了 createOptions() 方法。

在 C# 中,你不能在任何你想要的地方调用基本构造函数。基本构造函数总是在给定构造函数启动之前调用。你可以参考这个 url 来了解更多关于构造函数链:

http://www.yoda.arachsys.com/csharp/constructors.html

但是你可以通过稍微改变你的架构来得到你想要的。正如我所看到的,您的 options 属性是 Options 类的 ToString()。您不需要在构造函数时准备好此属性。

一些选项:

  1. 在 options get 访问器中将 Options 类转换为字符串。
  2. 消除 options 属性,而是实现一个 toString 方法,该方法将调用 createOptions 或仅调用它的内容

【讨论】:

  • 真棒链接真的帮助了我我改变了公共静态布尔不是静态的,它不需要。我几乎在继承的类构造函数中调用了覆盖函数,这解决了我的问题我注意到它在我的基类中被调用我忘记在上面的示例中发布它的那部分。
【解决方案2】:

所以这里有一些使用静态类成员(如public static bool steps)时的提示:

  1. 第一次加载类时,静态成员被初始化为其默认值(在这种情况下为 false)。请记住,静态成员属于类而不是实例,因此它们不能被覆盖,但可以使用 new 关键字隐藏在派生类中。

  2. 您可以使用称为静态构造函数的特殊构造函数来显式初始化静态类成员...因此您不应尝试在实例构造函数中初始化它们,如您的代码 sn-p 所示。

在 C# 静态成员上的快速 Google 搜索可能会有所帮助: Link to C# Help on Static Members

【讨论】:

    【解决方案3】:

    我在代码中没有看到Options类的构造函数,但我猜测它首先将给定的四个参数复制到对应的字段中,然后调用createOptions来初始化options字段。这实际上是一个很好的例子,说明为什么在构造函数中调用虚方法是不好的做法。在基类的构造函数完成之前,无法设置派生类的任何字段,因此被覆盖的方法将使用 steps 字段的默认值。

    有很多方法可以解决这个问题,但首先应该避免在构造函数中调用虚方法。我这样做的方法是将 options 属性设为只读并将其 getter 设为虚拟,以便它在需要时计算值。

    编辑。我没有注意到步骤是静态的。那我不明白你为什么要在实例构造函数中设置它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多