现在的位置: 首页 > 综合 > 正文

C#语言 第一部分 面向对象 (十) 方法的隐藏

2013年09月09日 ⁄ 综合 ⁄ 共 3918字 ⁄ 字号 评论关闭

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

  • 继承。超类修饰为public或protected的方法或属性可以被子类继承并访问;
  • 虚拟。虚拟的前提是可继承。超类中修饰为virtual关键字的方法或属性可以被子类继承覆盖;
  • 抽象。抽象的前提是可继承。超类中修饰为abstract关键字的方法或属性可以被子类继承实现,超类方法没有方法体,由子类提供;

现在我们来学习超类方法(或属性)和子类方法(或属性)的第四种联系——隐藏。

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

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Edu.Study.OO.Hiden {
 
    /// <summary>
    /// 定义一个球体类
10      /// </summary>
11      public class Ball {
12   
13          /// <summary>
14          /// 半径字段
15          /// </summary>
16          private double r;
17   
18          /// <summary>
19          /// 构造器,输入球体半径
20          /// </summary>
21          public Ball(double r) {
22              this.R = r;
23          }
24   
25          /// <summary>
26          /// 半径属性
27          /// </summary>
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          /// <summary>
42          /// 球体面积方法,返回球体面积,该方法虚拟
43          /// </summary>
44          public virtual double Area() {
45              return 4 * Math.PI * Math.Pow(this.R, 2);
46          }
47   
48          /// <summary>
49          /// 球体体积方法,返回球体体积,该方法虚拟
50          /// </summary>
51          public virtual double Volume() {
52              return (4F / 3F) * Math.PI * Math.Pow(this.R, 3);
53          }
54      }
55   
56   
57      /// <summary>
58      /// 圆柱体类,继承自球体
59      /// </summary>
60      public class Cylindrical : Ball {
61         
62          /// <summary>
63          /// 圆柱体高度
64          /// </summary>
65          private double height;
66   
67          /// <summary>
68          /// 构造器,输入半径和高度
69          /// </summary>
70          public Cylindrical(double r, double height)
71              : base(r) {
72              this.Height = height;
73          }
74   
75          /// <summary>
76          /// 高度属性
77          /// </summary>
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          /// <summary>
92          /// 覆盖超类中虚拟的面积方法,求圆柱体表面积
93          /// </summary>
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          /// <summary>
99          /// 隐藏超类中球体积的方法,改为求圆柱体体积
100          /// </summary>
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#提供此特性是为了保证语言的完整性,在一些特殊情况下可以解决一些问题。

Technorati 标签: ,

抱歉!评论已关闭.