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

本文关键字:字段 属性 派生 构造函数 获取 | 更新日期: 2023-09-27 18:03:07

我有两个类:

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" -不为空

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

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

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

另一个问题是Name2属性可能根本不存在于子类中,即使在定义的级别上:我可以从Class1派生Class3,并给它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;
    }
}

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

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

例子
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      

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

你做不到。它严格违反了面向对象方法编程的基本规则。

因为Class2的每个实例都有Name2属性。但是对于Class1的object实例,不能保证同样的情况。

你真的不清楚你想要实现什么。可以这样做,但我不认为这是一个好的做法:

    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参数。