C# 访问子类';来自基类的属性';建造师
我发现了一些奇怪的东西,我没想到会起作用,实际上起作用了。我可以从基类构造函数访问子类“(常量)属性:C# 访问子类';来自基类的属性';建造师,c#,oop,inheritance,polymorphism,C#,Oop,Inheritance,Polymorphism,我发现了一些奇怪的东西,我没想到会起作用,实际上起作用了。我可以从基类构造函数访问子类“(常量)属性: public abstract class Parent { public Parent() { var constName = ConstName; // <-- surprisingly, this works var randomName = RandomName; // <-- surprisingly, t
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(); } }
}
公共抽象类父类{
公共家长(){
var constName=constName;//Parent有一个抽象属性Parent.Name。由于单词abstract,您承诺Parent的(子类)实例将实现属性Name。如果它们不实现,则无法创建它的对象
请注意,我说的是:不能创建实例。如果子类没有实现属性名,则该类可以存在,但不能实例化它
类父级不实现属性名,因此不能实例化父级
然而,类Child实现了名称,因此您可以实例化它,并且因为您承诺类Parent的每个对象(=实例化)都有一个属性名称,所以您可以确保,尽管您所知道的只是它是父对象,但您也知道它有一个名称
这是亚型多态性的基本原理
这可能是您想要子类化的主要原因。您可以访问子类型的抽象/虚拟成员。属性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);
}
}
}
因此,不建议这样做。您在父对象中有Name属性!因此从技术上讲,这是合法的且正确的。@Nikita是的,但子对象尚未构造。请阅读我问题中的初始化顺序。属性编译为方法Get和Set,因此它就像您使用字符串return调用方法一样。它与const无关,它将将getter视为method.Run Code Analysis(FxCop),它将报告有意义的警告Yes。您指的是编译时契约,因此可以确定是否存在子属性。但这里的要点是,您是在子属性(完全)之前执行此操作的构造。这就是我不明白的?再看一遍,你的答案基本上解释(非常好)多态性的总体思想。但不是构造顺序,这是这个问题的核心。由于抽象函数,父类的构造函数知道要构造的对象是父类的子类。虽然子类的构造尚未完成,但子类已经完全存在。在每个类中构造函数,即使没有基类,也必须小心初始化对象项的顺序。可以调用方法和属性,但要确保它们只使用已初始化的项。对。因此,我对这种行为感到惊讶是正确的,因为它没有意义。我想这不容易o防止这种行为,因此编译器团队允许它,但创建了FxCop警告来告诉您这是一个“非常糟糕的想法”。基本上,这会导致非确定性的输出!我想我的问题可以这样想:仅仅因为编译了某个东西,并不意味着它“正确”。有一些奇怪的边缘情况是编译器无法教给你的。构造函数中有很多暗魔法:)。甚至可能有一些情况下它是有用的。你可以有属性,比如你的属性,它们返回常量或纯逻辑,不访问对象状态。你只需要知道你在做什么。非常正确,它在s中可能有用一些案例——对我来说,这就是为什么我偶然发现了这个问题。但我宁愿谨慎一点,因为这不是一个简单的问题……想象一下初级团队成员使用/滥用编译器边缘案例:-(。