02-24 面向对象--方法重载、隐藏
在面向对象思想中,由于基本特性--继承所致,产生了子类继承父类的关系,所以出现重载方法。
由于子类对象同事“汇聚了”父类和子类的方法所有公共方法,而C#并未对子类和父类的方法名称过多的 加以限制,因此会出现一些问题。
如果子类中的某个方法与父类方法的签名一致(即方法名和方法参数一样),那当通过子类对象访问此方法时,访问的是子类方法还是父类方法?
这就需要先从子类方法和父类方法之间的关系说起,总的来说,子类方法和父类方法之间的关系可以概括为一下三种。
- 扩充:子类方法,父类没有;
- 重载:子类有父类的同名函数,但参数类型或数目不一样;
- 完全相同:子类方法和父类方法从方法名称到参数类型完全一样。
对于第一种"扩充"关系,由于子类与父类方法不同名,所以不存在同名方法调用的问题,重点分析后两种情况。
(1)重载
在上面已介绍过方法重载的概念,再同一个类中构成重载的方法主要根据参数列表来决定调用哪一个。这一基本判断方法可以推广到类的继承情况。
1 namespace _20141212jicheng 2 { 3 class Parent //父类 4 { 5 public void OverloadF() //父类的方法 6 { 7 } 8 } 9 class Child : Parent //子类继承父类 10 { 11 public void OverloadF(int i)//子类的方法(带参数的方法) 12 { 13 } 14 } 15 }
使用代码如下:
1 static void Main(string[] args) 2 { 3 4 Child obj = new Child(); 5 obj.OverloadF(); //调用父类的重载方法 6 obj.OverloadF(100); //调用子类的重载方法 7 8 }
可看出,虽然重载的方法分布在不同的类中,但仍然可以将其看成是定义在同一类中的,其使用方法与调用类的其他方法并无不同。
(2)隐藏
当子类与父类拥有完全一样的方法时,称“子类隐藏了父类的同名方法”,请看实例项目。
1 class Parent //父类 2 { 3 public void HideF() //父类的方法 4 { 5 System.Console.WriteLine("Parent.HideF()"); 6 } 7 } 8 class Child : Parent //子类继承父类 9 { 10 public void HideF()//子类的方法 11 { 12 System.Console.WriteLine("Child.HideF()"); 13 } 14 }
注意现在子类和父类都拥有了一个完全相同的方法HideF(),于是问题就产生了:
1 Child c = new Child(); 2 c.HideF();//调用父类的还是子类的同名方法?
上述代码运行时,输出:
修改以下代码:
1 Parent p = new Parent(); 2 p.HideF();//调用父类的还是子类的同名方法?
上述代码运行结果:
由此得出结论:
当分别位于父类和子类的两个方法完全相同时,调用哪个方法由对象变量的类型决定。
然而,面向对象的继承特性允许使用子类对象被当成父类对象使用,这就问题复杂化了,以下代码运行时,会出现什么结果?
1 Child c = new Child(); 2 Parent p; 3 p = c; 4 p.HideF();//调用父类的还是子类的同名方法?
上述代码运行结果:
这就意味着即使Parent变量P中世纪引用的是Child类型的对象,通过P调用的方法还是Parent类的;
如果确实希望调用的子类的方法,应该这样使用:
1 ((Child) p).HideF();
运行结果:
即先进行强制类型转换。
回到前面的Parent和Child类的定义,VS在编译这两个类时,会发出一个不符合C#语句规范的警告,修改之后:
1 class Child : Parent //子类继承父类 2 { 3 public new void HideF()//子类的方法 4 { 5 System.Console.WriteLine("Child.HideF()"); 6 } 7 }
“new”关键字明确告诉C#编译器,子类隐藏父类的同名方法,提供自己的新版本。
由于子类隐藏了父类的同名方法,所以如果要在子类方法的实现代码中调用父类被隐藏的同名方法,请使用base关键字,代码如下:
base.HideF();//调用父类被隐藏的方法