我们先看一下这个例子:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Person p = new Manager();
Manager p2=new Manager();
p.Name = "Ahmad";
p.Introduce();
p.SayHello();
p2.SayHello();
p2 = (Manager)p;
p2.SayHello();
}
}
public abstract class Person
{
protected Person()
{
Name = "Reza";
Introduce();
}
public abstract string Name { get; set; }
public void SayHello()
{
Name = "Ali";
MessageBox.Show(Name);
}
public abstract void Introduce();
}
public class Manager : Person
{
public new void SayHello()
{
MessageBox.Show("Test2");
}
public override string Name { get; set; }
public override void Introduce()
{
MessageBox.Show("Hello " + Name);
}
}
}
起初我没有为基类编写构造函数。
据我所知,抽象方法的目的是强制派生类从中实现,因此我们无法在基类中实现抽象方法。
然后我添加了一个抽象属性。我看到我们可以在基类中初始化该属性并使用它。
1st:抽象的目的不仅仅是声明它们并让派生类来实现它吗?
为什么我们可以在基类中使用该属性?
我们最初可以实现一个非抽象的属性,它没有任何区别。
然后我添加了构造函数,事情变得更复杂。我们可以在构造函数中使用Introduce()方法从Child类调用Introduce()(我从调试器中理解)。
所以Child在这里继承了父亲,但我们在父亲的Child中调用了一个方法,这很奇怪,并且在某种程度上违反了继承规则。
第二:我错过了什么?
修改
答案 0 :(得分:2)
抽象的目的不仅是声明它们而是让它们衍生出来 上课实施吗?为什么我们可以在基类中使用该属性?
您无法在基类中使用抽象属性,因为您无法直接实例化它。您创建一个抽象属性的原因与您想要创建抽象方法的原因相同,这样可以确保派生类型实现它。
您的Name
媒体资源实际上并未使用基类实例。从SayHello
调用时,它将转到Name
的派生类型实现并使用它。
所以Child在这里继承了Father,但我们在Child中调用了一个方法 父亲,这是奇怪的,并以某种方式违反规则 遗产。我错过了什么?
它不仅奇怪,它的错误 可能导致运行时异常,因为子对象没有#t> t已经初始化了。如果您要访问Manager
中通过管理器构造函数(而不是通过字段初始化)实例化的Introduce
的任何成员,您将获得例外:
public class Manager : Person
{
public Manager()
{
s = "Hello";
}
private string s;
public override string Name { get; set; }
public override void Introduce()
{
Console.WriteLine(s.ToLower());
}
}
现在拨打Introduce
时,您会看到NullReferenceException
,因为s
尚未初始化。
如果要在派生类型上调用抽象方法,请确保在对象实例化后执行此操作。也许通过基础上的Initialize
方法。
您可以阅读Virtual member call in a constructor了解更多信息:
如果你在构造函数中进行虚拟方法调用,那么它不是 它的继承层次结构中的大多数派生类型,它将被调用 在一个没有运行构造函数的类上,因此可能没有 处于合适的状态,以便调用该方法。