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#提供此特性是为了保证语言的完整性,在一些特殊情况下可以解决一些问题。