Effective C# 学习笔记(三十四)避免在子类中重载父类的方法
2011-07-18 12:48 小郝(Kaibo Hao) 阅读(556) 评论(0) 编辑 收藏 举报首先,要分清orverload和override两个单词的中文解释。
overload为重载即表示方法通过参数个数、参数类型的不同对同名方法的另一逻辑实现,等于创建了一个新的同名方法,与原有方法并存。
override为覆写,顾名思义就是覆盖掉父类同名方法,形参列表是与父类一致的。
下面举例说明overload给程序带来的复杂问题:
//一个父类
using System;
using System.Collections.Generic;
namespace C_Sharp_Learning.Overload
{
public class B
{
public void Foo(D2 parm)
{
Console.WriteLine("In B.Foo");
}
public void Bar(B2 parm)
{
Console.WriteLine("In B.Bar");
}
public void Foo2(IEnumerable<D2> parm)
{
Console.WriteLine("In B.Foo2");
}
}
}
//一个子类
using System;
using System.Collections.Generic;
namespace C_Sharp_Learning.Overload
{
public class D : B
{
public void Foo(B2 parm)
{
Console.WriteLine("In D.Foo");
}
public void Bar(B2 parm1, B2 parm2 = null)
{
Console.WriteLine("In D.Bar");
}
public void Foo2(IEnumerable<B2> parm)
{
Console.WriteLine("In D.Foo2");
}
}
}
//一个参数父类
namespace C_Sharp_Learning.Overload
{
public class B2
{
}
}
//一个参数子类
namespace C_Sharp_Learning.Overload
{
public class D2 : B2
{
}
}
Console.WriteLine("-----------overload-----------");
var obj2 = new D();
Console.WriteLine(obj1);//C_Sharp_Learning.Overload.D
obj2.Foo(new D2());//In D.Foo 即使父类的方法形参列表更复合参数类型,但编译器依然认为子类的重载优先级更高,所以调用了子类的方法
obj2.Foo(new B2());//In D.Foo
C_Sharp_Learning.Overload.B obj3 = new D();
Console.WriteLine(obj3);//C_Sharp_Learning.Overload.D 运行时解析为子类
obj3.Foo(new D2());//In B.Foo(由于在编译时obj3定义为B类型,所以obj3.Foo方法调用的是父类的Foo)
var obj4 = new D();
(obj4 as C_Sharp_Learning.Overload.B).Foo(new D2());//In B.Foo 可用类型转换来控制调用父类的方法
obj4.Foo(new B2());//In D.Foo
obj1 = new D();
obj1.Bar(new D2());//In D.Bar 利用C#4.0 可选参数特性进行的重载,依然使用了子类的方法
(obj1 as C_Sharp_Learning.Overload.B).Bar(new D2());//In B.Bar 依然利用类型临时转换调用父类的方法
var sequence = new List<D2> { new D2(), new D2() };
obj2 = new D();
obj2.Foo2(sequence);
/*
这里的情况比较复杂,在c#4.0以前的版本,应该是调用父类的方法,因为那时C#的范型不支持协变和逆变,所以输出为In B.Foo2
而在C#4.0中,引入了范型类型的协变逆变特性,所以输出为In D.Foo2
*/
如上代码所展现的,子类对于父类方法的重载是不易被理解的,也是很容易引发类的使用者的使用错误。子类的重载的优先级默认是高于父类的方法的,即使父类的方法的参数类型更符合调用参数的类型也是如此。另外注意C#4.0版本前后对范型的校验规则因协变逆变的支持不同,会产生更多运行时版本兼容性的问题,所以尽量避免在子类中重载父类的方法。
出处:http://www.cnblogs.com/haokaibo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。