当前位置:   article > 正文

深入继承续——虚方法、override 、new_虚方法和new的区别

虚方法和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。

下面是代码实现:

  1. public interface I_9_A
  2. {
  3. int Age { get;set;}
  4. string GetName();
  5. string GetPwd();
  6. }
  7. /// <summary>
  8. /// 下面这个类继承了A接口,并实现了里面的全部成员
  9. /// </summary>
  10. public class I_9_L_1 : I_9_A
  11. {
  12. protected int age;
  13. protected string name;
  14. protected string pwd;
  15. public I_9_L_1()
  16. {
  17. age = 28;
  18. name = "提高班";
  19. pwd = "tgb";
  20. }
  21. public int Age
  22. {
  23. get { return age; }
  24. set { age = value; }
  25. }
  26. public string GetName()
  27. {
  28. return name;
  29. }
  30. public string GetPwd()
  31. {
  32. return pwd;
  33. }
  34. }
  35. public class I_9_L_2 : I_9_L_1
  36. {
  37. public new string GetName()
  38. {
  39. return ":" + name;
  40. }
  41. public new string GetPwd()
  42. {
  43. return "密码:" + pwd;
  44. }
  45. }
  46. /**当我们看了上面的演示以后会发现一个很严重的问题,
  47. * 我们明明就调用的2这个类,可为什么方法却依然是1哪个类的呢?
  48. * 原因就在2这个类虽然是复写了1类中的方法,但是他并没有去改写1类中的方法
  49. **/
  50. ///
  51. /// <summary>
  52. /// 下面这个类继承了A接口,并实现了里面的全部成员
  53. /// </summary>
  54. public class I_9_L_3 : I_9_L_1
  55. {
  56. protected int age;
  57. protected string name;
  58. protected string pwd;
  59. public I_9_L_3(int a, string n, string p)
  60. {
  61. age = a;
  62. name = n;
  63. pwd = p;
  64. }
  65. public int Age
  66. {
  67. get { return age; }
  68. set { age = value; }
  69. }
  70. public virtual string GetName()
  71. {
  72. return name;
  73. }
  74. public virtual string GetPwd()
  75. {
  76. return pwd;
  77. }
  78. }
  79. public class I_9_L_4 : I_9_L_3
  80. {
  81. public I_9_L_4(int a, string n, string p)
  82. : base(a, n, p)
  83. {
  84. age = a;
  85. name = n;
  86. pwd = p;
  87. }
  88. public override string GetName()
  89. {
  90. return "我是:" + name;
  91. }
  92. public override string GetPwd()
  93. {
  94. return "密码是:" + pwd;
  95. }
  96. }
  97. /**
  98. * 其实这个例题理解起来不难的,首先我们知道他整个的运行顺序
  99. * 然后就是,如果发现不是虚方法,那么就直接调用了,但是如果是他就会继续往下找,一直找到不是虚的位置.
  100. *
  101. * 我们这个例题说完了,不知道你有没有想起我们前面说过的一个问题,就是显示实现的无法使用修饰符,
  102. * 既然不能使用修饰符,那virtual也没法用,难道显示实现的方法就不能使用虚方法了吗?
  103. *
  104. * 答案是否定的,呵呵
  105. *
  106. * 我们可以在这个显示实现中调用另一个方法嘛,哈哈,然后这个被调用的方法再是虚方法,我想法律不会不允许吧
  107. * **/
  108. ///
  109. /// <summary>
  110. /// 下面这个类继承了A接口,并实现了里面的全部成员
  111. /// </summary>
  112. public class I_9_L_5 : I_9_A
  113. {
  114. protected int age;
  115. protected string name;
  116. protected string pwd;
  117. public I_9_L_5(int a, string n, string p)
  118. {
  119. age = a;
  120. name = n;
  121. pwd = p;
  122. }
  123. public int Age
  124. {
  125. get { return age; }
  126. set { age = value; }
  127. }
  128. public string GetName()
  129. {
  130. return name;
  131. }
  132. public string GetPwd()
  133. {
  134. return pwd;
  135. }
  136. }
  137. public class I_9_L_6 : I_9_L_5,I_9_A
  138. {
  139. public I_9_L_6(int a, string n, string p)
  140. : base(a, n, p)
  141. {
  142. age = a;
  143. name = n;
  144. pwd = p;
  145. }
  146. public string GetName()
  147. {
  148. return "我是:" + name;
  149. }
  150. public string GetPwd()
  151. {
  152. return "密码是:" + pwd;
  153. }
  154. }
  155. }

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


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/950608
推荐阅读
相关标签
  

闽ICP备14008679号