深入继承续——虚方法、override 、new

虚方法

virtual 关键字用于修饰方法、属性、索引器或事件声明,并且允许在派生类中重写这些对象。例如,此方法可被任何继承它的类重写。

当类中的方法声明前加上了virtual修饰符,我们称之为虚方法,反之为非虚。    
 若希望或预料到基类的这个方法在将来的派生类中会被重写(override ),则此方法必须被声明为 virtual。

调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。

默认情况下,方法是非虚拟的。不能重写非虚方法。

virtual 修饰符不能与 staticabstract, private  override 修饰符一起使用。

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

·        在静态属性上使用 virtual 修饰符是错误的。

·        通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

 

 

虚方法的定义形式

virtual 修饰符 返回的数据类型方法名(参数表)

{

    方法体

}

 

对于非虚的方法,无论被其所在类的实例调用,还是被这个类的派生类的实例调用,方法的执行方式不变。而对于虚方法,它的执行
方式可以被派生类改变,这种改变是通过方法的重载来实现的。

 

虚方法的重载形式

override 修饰符 返回的数据类型方法名(参数表)

{

    方法体

}

override 重写继承自基类的 virtural 方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)。

 

New和override的异同

 new和override的相同点:

 都可以对基类成员进行隐藏,都可以用base关键字调用基类的成员 

 new和override的不同点:

 用override的基类的方法必须要用virtual,而new不必要

 本质区别在于当派生类对象作为基类类型使用时,override 的执行派生类方法,new 的执行基类方法。如果作为派生类类型调用,则都是执行 override 或 new 之后的。

 

  override 重写继承自基类的 virtural 方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)。

   new 隐藏继承自基类的 virtual 方法,老房子还留着,在旁边盖个新房,想住新房住新房(作为派生类对象调用),想住老房住老房(作为基类对象调用)。

   当派生类中出现与基类同名的方法,而此方法前面未加 override 或 new 修饰符时,编译器会报警告,但不报错,真正执行时等同于加了 new。

下面是代码实现:

 public interface I_9_A
    {
        int Age { get;set;}
        string GetName();
        string GetPwd();
    }
    /// <summary>
    /// 下面这个类继承了A接口,并实现了里面的全部成员
    /// </summary>
    public class I_9_L_1 : I_9_A
    {
        protected int age;
        protected string name;
        protected string pwd;

        public I_9_L_1()
        {
            age = 28;
            name = "提高班";
            pwd = "tgb";
        }

        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        public string GetName()
        {
            return name;
        }
        public string GetPwd()
        {
            return pwd;
        }
    }
    public class I_9_L_2 : I_9_L_1
    {
        public new string GetName()
        {
            return ":" + name;
        }
        public new string GetPwd()
        {
            return "密码:" + pwd;
        }
    }

    /**当我们看了上面的演示以后会发现一个很严重的问题,
     * 我们明明就调用的2这个类,可为什么方法却依然是1哪个类的呢?
     * 原因就在2这个类虽然是复写了1类中的方法,但是他并没有去改写1类中的方法
    **/
    ///
    /// <summary>
    /// 下面这个类继承了A接口,并实现了里面的全部成员
    /// </summary>
    public class I_9_L_3 : I_9_L_1
    {
        protected int age;
        protected string name;
        protected string pwd;

        public I_9_L_3(int a, string n, string p)
        {
            age = a;
            name = n;
            pwd = p;
        }

        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        public virtual string GetName()
        {
            return name;
        }
        public virtual string GetPwd()
        {
            return pwd;
        }
    }
    public class I_9_L_4 : I_9_L_3
    {
        public I_9_L_4(int a, string n, string p)
            : base(a, n, p)
        {
            age = a;
            name = n;
            pwd = p;
        }
        public override string GetName()
        {
            return "我是:" + name;
        }
        public override string GetPwd()
        {
            return "密码是:" + pwd;
        }
    }

    /**
     * 其实这个例题理解起来不难的,首先我们知道他整个的运行顺序
     * 然后就是,如果发现不是虚方法,那么就直接调用了,但是如果是他就会继续往下找,一直找到不是虚的位置.
     * 
     * 我们这个例题说完了,不知道你有没有想起我们前面说过的一个问题,就是显示实现的无法使用修饰符,
     * 既然不能使用修饰符,那virtual也没法用,难道显示实现的方法就不能使用虚方法了吗?
     * 
     * 答案是否定的,呵呵
     * 
     * 我们可以在这个显示实现中调用另一个方法嘛,哈哈,然后这个被调用的方法再是虚方法,我想法律不会不允许吧
     * **/
    ///
    /// <summary>
    /// 下面这个类继承了A接口,并实现了里面的全部成员
    /// </summary>
    public class I_9_L_5 : I_9_A
    {
        protected int age;
        protected string name;
        protected string pwd;

        public I_9_L_5(int a, string n, string p)
        {
            age = a;
            name = n;
            pwd = p;
        }

        public int Age
        {
            get { return age; }
            set { age = value; }
        }

        public string GetName()
        {
            return name;
        }
        public string GetPwd()
        {
            return pwd;
        }
    }
    public class I_9_L_6 : I_9_L_5,I_9_A
    {
        public I_9_L_6(int a, string n, string p)
            : base(a, n, p)
        {
            age = a;
            name = n;
            pwd = p;
        }
        public  string GetName()
        {
            return "我是:" + name;
        }
        public string GetPwd()
        {
            return "密码是:" + pwd;
        }
    }
}

---------------------------原文参考CSDN和天轰穿视频


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值