• 天轰穿C# vs2010 04面向对象的编程之虚成员和重写【原创】


    老田: 所谓虚成员就是指在基类中申明了方法、属性、索引器或事件,也做一个最简单的处理,但是无法预料在派生类中该方法是否需要被改写。那使用virtual关键字将成员申明为虚成员。这就使它们可以在派生类中被重写。例如,此方法可被任何继承它的类重写。

           小天:可以来个比较实际,好用的实例不?你上面的那个汽车类(4.9.1的第二个示例),我想了很久才想到用一个汽车经销商卖车情况来做示例。

           老田:好嘛,前面不是写了一个计算面积的类吗?不过那个类太简单了,下面我们做一个可以计算多种形状面积的类库。类关系图如图4-29

     

                                                     图4-29

           根据上面的实例,尝试自己先写写,然后在对比下面的代码:

        //----------------------基类----------------------------

        public class Dimensions

        {

            public const double PI = Math.PI;

            protected double x, y;

            public Dimensions()

            {//一个无参数的构造函数

    //如果没有这个构造函数,CRL是否会自动添加一个空的呢?

            }

            public Dimensions(double x, double y)

            {//构造函数

                this.x = x;

                this.y = y;

            }

     

            public virtual double Area()

            {//计算面积,虚方法,等待被重写

                return x * y;

            }

        }

        //---------------------类Circle-继承Dimensions-------------------

        public class Circle : Dimensions

        {//圆

            public Circle(double r)

                : base(r, 0)

            {

            }

     

            public override double Area()

            {

                return PI * x * x;

            }

        }

        //---------------------类Sphere-继承Dimensions-------------------

        class Sphere : Dimensions

        {//球体

            public Sphere(double r)

                : base(r, 0)

            {

            }

     

            public override double Area()

            {

                return 4 * PI * x * x;

            }

        }

        //---------------------类Cylinder-继承Dimensions-------------------

        class Cylinder : Dimensions

        {//圆柱体

            public Cylinder(double r, double h)

                : base(r, h)

            {

            }

     

            public override double Area()

            {

                return 2 * PI * x * x + 2 * PI * x * y;

            }

        }

           根据上面那个计算面积的实例稍微改变来实现使用上面这个类,需要注意的是,这个实例中的输入文本框使用了是maskedTextBox控件(怎么用就不说了,自己看控件的mask属性),界面如图4-30

     

                                图4-30

           在“计算”按钮的事件中代码如下:

            private void button1_Click(object sender, EventArgs e)

            {

                //将界面上两个TextBox中的字符接收过来并转换为double类型

                double x = double.Parse(mtb_x.Text);

                double y = double.Parse(mtb_y.Text);

                //注意,这里是一次申明,但是在分别用不同的类来实例化而实现调用不同类中重写的方法

                Dimensions ds;   //注意这里申明的是一个基类型的变量

                switch (cb_type.Text)

                {

                    case "X方形":

                        ds = new Dimensions(x, y);  //用基类型实例化变量

                        //下面调用的方法是Dimensions类中的Area方法

                        lbl_result.Text = ds.Area().ToString();

                        break;

                    case "圆":

                        ds = new Circle(x);         //用Dimensions的派生类Circle来实例化

                        //下面调用的方法是Circle类中的Area方法

                        lbl_result.Text = ds.Area().ToString();

                        break;

                    case "球体":

                        ds = new Sphere(x);         //用Dimensions的派生类Sphere来实例化

                        //下面调用的方法是Sphere类中的Area方法                   

                        lbl_result.Text = ds.Area().ToString();

                        break;

                    case "圆柱":

                        ds = new Cylinder(x, y);    //用Dimensions的派生类Cylinder来实例化

                        //下面调用的方法是Dimensions类中的Area方法                   

                        lbl_result.Text = ds.Area().ToString();

                        break;

                    default:

                        MessageBox.Show("请选择计算类型");

                        cb_type.Focus();//将焦点设置到选择类型的下拉框上去

                        break;

                }

            }

           注意读下上面的代码中,实际上类对象我们只是用基类Dimensions申明了一个。而最终调用方法也是完全一样的。剩下不一样的只在于对于不同的计算类型使用了不同的类来实现。于是乎就实现了不同类型的计算方式采用不同的计算方法(换句话说是调用了不同类中的Area方法)。其实C#在调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。

    默认情况下,方法是非虚拟的。不能重写非虚方法。 virtual 修饰符不能与 static、abstract、private 或 override 修饰符一起使用。

    除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。

    • 在静态属性上使用 virtual 修饰符是错误的。
    • 通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

     

    另外,上面这段代码中有一处注释是错误的,找出来。

    本文章为天轰穿原创作品,转载请注明出处及作者。

  • 相关阅读:
    ES 分词器设置+同义词设置
    ES 重写分数查询
    ReadWriteLock源码阅读
    java编程之Lambda、Stream、Optional
    AQS源码阅读
    MinIOGithub标星19K+Star,10分钟自建对象存储服务!
    使用Jenkins一键打包部署SpringBoot应用,就是这么6!
    网络与系统攻防技术|实验四 恶意代码分析实践
    React的通信方式与状态管理:Redux与Mobx
    React新旧版本生命周期对比
  • 原文地址:https://www.cnblogs.com/thcjp/p/2862572.html
Copyright © 2020-2023  润新知