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 ....我需要通用代码
您不能(更重要的是,您不应该)这样做。当你在基类的构造函数中,子类部分还没有初始化,所以没有办法得到子类的成员:很简单,它们还不存在。
另一个问题是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参数。