为什么被重写的虚拟属性总是指向基类的属性的 getter 和 setter 方法
本文关键字:属性 getter 基类 setter 方法 重写 虚拟 为什么 | 更新日期: 2023-09-27 18:35:29
一个理论问题。我在类中有一个虚拟属性。另一个扩展该类的类,即使覆盖了虚拟属性,似乎从未真正覆盖基属性的 getter 或 setter 方法。我错过了什么?
class BaseClass
{
protected string bla;
public virtual string Bla
{
get { return this.bla; }
set { this.bla = value; }
}
protected BaseClass() { }
public BaseClass(string _bla)
{
this.Bla = _bla;
}
}
class ChildClass : BaseClass
{
private string bla2;
public override string Bla
{
get
{
return bla2;
}
set
{
bla2 = value;
}
}
public ChildClass(string _bla2) : base("AAA")
{
this.Bla = _bla2;
}
}
class Program
{
static void Main(string[] args)
{
var c = new ChildClass("Me");
Console.WriteLine(c.Bla);
Console.ReadLine();
}
}
我想,我得到了答案。
如果修复代码以便编译,它将按预期工作。但是,请注意我添加的评论!您正在从构造函数调用虚拟方法(属性资源库,但仍然是方法)。这很糟糕。
using System;
namespace Demo
{
class BaseClass
{
protected string bla;
public virtual string Bla
{
get
{
return this.bla;
}
set
{
this.bla = value;
}
}
protected BaseClass()
{
}
public BaseClass(string _bla)
{
this.Bla = _bla;
}
}
class ChildClass: BaseClass
{
private string bla2;
public override string Bla
{
get
{
return bla2;
}
set
{
bla2 = value;
}
}
public ChildClass(string _bla2)
: base("AAA")
{
// Step into the next line of code in the debugger.
// You'll see that it goes into the ChildClass.Bla setter.
// However note that this is making a virtual call in a constructor
// - which is very bad if there is a further derived class because
// it will call a method in that derived class before that derived
// class has been constructed.
// You can fix this potential problem by making this entire class
// sealed or by making the property sealed in this class.
this.Bla = _bla2;
}
}
class Program
{
private void run()
{
var c = new ChildClass("X");
}
static void Main(string[] args)
{
new Program().run();
}
}
}
base("AAA")
调用public BaseClass(string _bla) { this.Bla = _bla; }
,将this.Bla
的值(在子类中它指向字段bla2
)设置为"AAA",因此在public ChildClass(string _bla2) { this.Bla = _bla2; }
this.Bla
和bla2
中已经通过基构造函数分配。
我用你的代码做了一个单元测试,它可以工作,添加子类:
public override string ToString()
{
return string.Format("bla = {0},bla2 ={1}", bla,bla2);
}
设置属性后调用此方法。
你会看到bla=null
和bla2="Something"
编辑如评论中所述,我不得不将 setter 的可见性级别更改为公共,删除子类中的构造函数