C#面向对象(十):方法的隐藏_ASP.NET学习网_ASP.NET教程|ASP.NET MVC|LINQ|VS2010|jQuery|WPF|Silverlight

来源:百度文库 编辑:神马文学网 时间:2024/06/13 07:35:45

我们前面讲过了类和类之间的继承关系,我们了解到,超类方法和子类方法(或属性)可以具备三种联系方式。

继承。超类修饰为public或protected的方法或属性可以被子类继承并访问;
虚拟。虚拟的前提是可继承。超类中修饰为virtual关键字的方法或属性可以被子类继承或覆盖;
抽象。抽象的前提是可继承。超类中修饰为abstract关键字的方法或属性可以被子类继承并实现,超类方法没有方法体,由子类提供;
现在我们来学习超类方法(或属性)和子类方法(或属性)的第四种联系——隐藏。

子类继承超类方法,并一个和该方法同名、同参数的新方法,子类方法前不使用override关键字修饰。这种情况子类隐藏了超类继承的一个方法。

隐藏和覆盖最大的不同:隐藏的方法只能用该方法所属的类的变量访问,使用超类变量则无法访问,只能访问被隐藏的方法。看例子:

1   using System;
2   using System.Collections.Generic;
3   using System.Linq;
4   using System.Text;
5    
6   namespace Edu.Study.OO.Hiden {
7    
8       ///


9       /// 定义一个球体类
10       ///

11       public class Ball {
12    
13           ///
14           /// 半径字段
15           ///

16           private double r;
17    
18           ///
19           /// 构造器,输入球体半径
20           ///

21           public Ball(double r) {
22               this.R = r;
23           }
24    
25           ///
26           /// 半径属性
27           ///

28           public double R {
29               get {
30                   return this.r;
31               }
32               set {
33                   if (value > 0) {
34                       this.r = value;
35                   } else {
36                       Console.WriteLine("半径长度必须大于0。");
37                   }
38               }
39           }
40    
41           ///
42           /// 球体面积方法,返回球体面积,该方法虚拟
43           ///

44           public virtual double Area() {
45               return 4 * Math.PI * Math.Pow(this.R, 2);
46           }
47    
48           ///
49           /// 球体体积方法,返回球体体积,该方法虚拟
50           ///

51           public virtual double Volume() {
52               return (4F / 3F) * Math.PI * Math.Pow(this.R, 3);
53           }
54       }
55    
56    
57       ///
58       /// 圆柱体类,继承自球体
59       ///

60       public class Cylindrical : Ball {
61           
62           ///
63           /// 圆柱体高度
64           ///

65           private double height;
66    
67           ///
68           /// 构造器,输入半径和高度
69           ///

70           public Cylindrical(double r, double height)
71               : base(r) {
72               this.Height = height;
73           }
74    
75           ///
76           /// 高度属性
77           ///

78           public double Height {
79               get {
80                   return this.height;
81               }
82               set {
83                   if (value > 0) {
84                       this.height = value;
85                   } else {
86                       Console.WriteLine("高度必须大于0。");
87                   }
88               }
89           }
90    
91           ///
92           /// 覆盖超类中虚拟的面积方法,求圆柱体表面积
93           ///

94           public override double Area() {
95               return (2 * Math.PI * this.R * this.Height) + (Math.PI * Math.Pow(this.R, 2) * 2);
96           }
97    
98           ///
99           /// 隐藏超类中球体积的方法,改为求圆柱体体积
100           ///

101           public new double Volume() {
102               return Math.PI * Math.Pow(this.R, 2) * this.Height;
103           }
104       }
105    
106       class Program {
107    
108           static void Main(string[] args) {
109    
110               // 输出Ball类对象Area方法和Volume方法的返回值
111               Ball ball = new Ball(20);
112               Console.WriteLine("Ball's area = {0}", ball.Area());
113               Console.WriteLine("Ball's area = {0}", ball.Volume());
114    
115               // 输出Cylindrical类对象Area方法和Volume方法的返回值
116               Cylindrical cyl = new Cylindrical(20, 30);
117               Console.WriteLine("Cylindrical's area = {0}", cyl.Area());
118               Console.WriteLine("Cylindrical's area = {0}", cyl.Volume());
119    
120    
121               // 令Ball类的变量引用到Cylindrical类的对象上
122               ball = cyl;
123               Console.WriteLine("Ball's area = {0}", ball.Area());    // 此处调用Area方法时,调用的其实是Cylindrical类的Area方法
124               Console.WriteLine("Ball's area = {0}", ball.Volume());    // 此处调用Volume方法时,调用的其实是Ball类的方法
125           }
126       }
127   }

从代码中可以清楚的看到覆盖和隐藏具体的区别,当使用超类变量引用到子类实例后,依旧可以访问子类覆盖后的方法,但无法访问到子类隐藏后的方法,只能访问被子类隐藏的方法。

注意,本例是为了让大家看明白覆盖和隐藏的区别,对于隐藏来说,被隐藏的超类方法无须修饰为virtual。

一半,子类方法要隐藏父类方法,在方法声明前加上new关键字,表示此方法是被隐藏的方法。new关键字并不是必需的。

隐藏表示了这样一种含义:子类定义了和超类名称相同但流程不同的方法,但只能以子类类型可以访问,使用超类类型则无法访问。

隐藏的情况较之覆盖要少见一些,以至于许多面向对象语言(例如Java)并不提供方法的隐藏。C#提供此特性是为了保证语言的完整性,在一些特殊情况下可以解决一些问题。