当我们仍然可以在抽象类中使用它们时,抽象属性的目的是什么?

时间:2015-02-05 12:27:36

标签: c# .net inheritance

我们先看一下这个例子:

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中调用了一个方法,这很奇怪,并且在某种程度上违反了继承规则。

第二:我错过了什么?

修改

enter image description here

enter image description here

1 个答案:

答案 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了解更多信息:

  

如果你在构造函数中进行虚拟方法调用,那么它不是   它的继承层次结构中的大多数派生类型,它将被调用   在一个没有运行构造函数的类上,因此可能没有   处于合适的状态,以便调用该方法。