访问子类'基地的财产'构造函数

时间:2015-09-29 06:20:01

标签: c# oop inheritance polymorphism

我发现了一些奇怪的东西,我没想到它会起作用,实际上是有效的。我可以访问一个子类'来自基类的(常数)财产'构造:

public abstract class Parent {

  public Parent() {
    var constName = ConstName;            // <-- surprisingly, this works  
    var randomName = RandomName;          // <-- surprisingly, this works  
  }

  public abstract string ConstName { get; }

  public abstract string RandomName { get; }

}


public class Child : Parent {

  public override string ConstName { get { return "Mike"; } }

  public override string RandomName { get { return new Random().Next().ToString(); } }

}

Name是非静态属性而不是字段。我一直认为类型的初始值设定项(用于staticconst字段)被执行,然后是基类的那些,然后是基本的ctor,然后是子类&#39;构造函数。 这意味着孩子在父母的陪伴下还没有完全构建。

这是&#34;合法&#34;在所有情况下都可以使用的C#?为什么这样做?

编辑:

不,这不是一个愚蠢的问题。那个人在我的问题中没有类模式。

2 个答案:

答案 0 :(得分:4)

Parent有一个抽象属性Parent.Name。由于单词abstract,您保证(子类)Parent的实例将实现属性Name。如果他们不这样做,你就无法创造它的对象。

  

请注意,我说:无法创建实例。如果子类没有实现属性Name,则该类可以存在,但是您无法实例化它。

Class Parent没有实现属性Name,因此您无法实例化Parent。

然而,

Class Child实现了Name,因此你可以实例化它,并且因为你承诺类Parent的每个对象(=实例化)都有一个属性Name,你可以肯定,尽管你所知道的只是它是一个Parent,你也知道它有一个名字。

这是子类型中多态的基本原理 Wikipedia about polymorphism

这可能是您想要进行子类化的主要原因。

答案 1 :(得分:3)

您可以访问子类型的抽象/虚拟成员。属性getter最终是方法。

但是

正如您所说,子类构造函数尚未执行。因此,它可能有副作用。这就是你从FxCop收到警告的原因。

public abstract class Parent
{
  public Parent() 
  {
    // NullReferenceException here:
    var nameLength = Name.Length;
  }

  public abstract string Name { get; }

}

public class Child : Parent 
{
  private string name;

  public Child()
  {
    name = "My Name";
  }

  public override string Name { get { return name; } }
}

更糟糕的是:

public class Child : Parent 
{
  private string name;

  public Child()
  {
    name = "My Name";
  }

  public override string Name
  { 
    get 
    { 
      // NullReferenceException here.
      // You didn't expect that this code is executed before
      // the constructor was, did you?
      return name.Substring(0, name.Length - 1);
    } 
  }
}

因此不建议这样做。