c#在基础构造函数中获取派生类的字段(属性)值

时间:2013-03-10 12:48:23

标签: c# constructor base derived-class

我有2个班级:

public class Class1
{
   private string Name1;
   public Class1()
   {
      //How to get Name2 of the derived class?
   }  
}

public class Class2 : Class1
{
   private string Name2 = "asd"; 
   public Class2(){}
}

如何在基础构造函数中获取派生类的Name2

public class Class1
{
   private string Name1;
   public Class1()
   {
       class2 xxx = this as class2      
       if (class2 != null) 
          this.Name1 = xxx.Name2;
   }  
}

“this as class2” - 不为空

这个例子是正确的。唯一的问题是我不知道Derived类是Class2还是class3或class4 ....我需要通用代码

5 个答案:

答案 0 :(得分:2)

你不能(更重要的是,你不应该)这样做。当你在基类的构造函数中时,子类部分还没有被初始化,所以没有办法到达子类的成员:很简单,它们还不存在。

另一个问题是,Name2属性可能根本不存在于子类中,即使在定义的级别:我可以从Class3派生Class1,然后给它Name3属性而不是Name2

所有这些都没有涉及破坏封装这样的“无关紧要”的问题:Name2是私人成员,可能会在Class2的未来实施中删除。

子类在构造函数中将事物传递给超类的唯一方法是传递参数。这可行:

public class Class1 {
    private string Name1;
    public Class1(string subclassName2)
    {
        // Subclass has passed its Name2 here
    }  
}

public class Class2: class1 {
    private string Name2; 
    public Class2(string myName) : base(myName) {
        Name2 = myName;
    }
}

答案 1 :(得分:1)

您可以从基类代码访问派生类中的代码,但只能从实际上是派生类对象的对象中访问,并且只有在涉及的方法是虚方法时才能访问。

如果你有一个对象本身就是基类的一个实例,那么从那个实例中你就看不到基类的派生类代码了。

例如

public class Baseclass{

  public void Foo()
  {
      Bar();
  }
  public virtual void Bar()
  {
     print("I'm a BaseClass");}}


public classs Derived: BaseClass{

  public override void Bar()
  {
     print("I'm a Derived Class");}}


Main()

   var b = new BaseClass();
   x.Foo()  // prints "I'm a BaseClass" 
   // This Foo() calls Bar() in base class  
    var d = new Derived();
   d.Foo()  // prints "I'm a Derived Class" 
   // in above, the code for Foo() (in BaseClass)
   //  is accessing Bar() in derived class      

答案 2 :(得分:0)

我认为你不能因为当你实例化派生类时,首先调用基类构造函数来初始化基类,然后初始化派生类。在基类构造函数中,没有办法访问派生类成员,因为它们是当时不可用。

答案 3 :(得分:0)

你不能这样做。它严格违反了面向对象方法的编程基础规则。

由于Class2的每个实例都具有Name2属性。但对Class1的对象实例无法保证同样的效果。

答案 4 :(得分:0)

你想要实现的目标并不是很清楚。可以做到以下几点,但我认为这不是一个好习惯:

    interface IHasName2
    {
        string Name2 { get; }
    }
    class Class1
    {
        string Name1;

        public Class1()
        {
            var withName2 = this as IHasName2;
            if (withName2 != null)
            {
                Name1 = withName2.Name2;
            }
        }
    }

然后,如果他们愿意,那么派生自Class1的类可以实现IHasName2

但是,您可能希望abstract类确保派生类指定Name2。它可能是这样的:

    abstract class Class1
    {
        string Name1;

        // instance property required to be implemented by deriving classes
        protected abstract string Name2 { get; }

        // instance constructor
        protected Class1()
        {
            // 'Name2' can be read already here (dangerous?)
            Name1 = Name2;
        }
    }

最后,考虑一下dasblinkenlight提出的简单解决方案,让Class1的实例构造函数接受名称的string参数。然后派生类在它们“链接”它们的基类构造函数时必须提供该name参数。