Effective C# 学习笔记(二十三)理解接口方法和虚方法的区别
2011-07-13 16:14 小郝(Kaibo Hao) 阅读(404) 评论(0) 编辑 收藏 举报接口和虚方法的使用的场景各有所指,总的来说实现接口要比重载virtual方法更具有灵活性。你可以sealed、virtual实现的方法或用 abstract来定义方法契约,甚至可以在实现接口的方法中调用virtual方法来获取子类对父类方法重载的多态控制,和父类对自己实现的统一控制。 父类的虚方法可以提供所有子类对该方法的默认实现,而接口提供了多种方法定义组合(因为可以被多继承),对外提供了更加灵活的暴露契约的方式。
特征:
- 接口的方法默认声明为不是Virtual的
- 子类不能重载父类实现接口的方法
对于此类需求可以使用new 关键字实现,例如有个类实现了接口IMsg,IMsg有个方法Message()
所以MyClass必须事先Message()方法。而MyClass又有一个子类继承自它,也实现了Message()方法,但此方法并没有覆盖掉父类的Message()方法。代码如下:
interface IMsg
{
void Message();
}
public class MyClass : IMsg
{
public void Message()
{
Console.WriteLine("MyClass");
}
}
public class MyDerivedClass : MyClass
{
public void Message()
{
Console.WriteLine("MyDerivedClass");
}
}
MyDerivedClass d = new MyDerivedClass();
d.Message(); // prints "MyDerivedClass".
IMsg m = d as IMsg;
m.Message(); // prints "MyClass"
若要显示地覆盖掉该方法,应用new关键字来显示覆盖该方法
public class MyDerivedClass : MyClass
{
public new void Message()
{
Console.WriteLine("MyDerivedClass");
}
}
MyDerivedClass d = new MyDerivedClass();
d.Message(); // prints "MyDerivedClass".
IMsg m = d as IMsg;
m.Message(); // prints " MyDerivedClass "
但是这时只是覆盖了父类实现借口的方法,并没有覆盖掉父类自己的实现,见如下代码:
MyDerivedClass d = new MyDerivedClass();
d.Message(); // prints "MyDerivedClass".
IMsg m = d as IMsg;
m.Message(); // prints "MyDerivedClass"
MyClass b = d;
b.Message(); // prints "MyClass"
若要子类在覆盖父类实现接口方法的同时,也覆盖掉父类的方法应声明为virtual的,而子类应以override关键字进行重载,代码如下:
public class MyClass : IMsg
{
public virtual void Message()
{
Console.WriteLine("MyClass");
}
}
public class MyDerivedClass : MyClass
{
public override void Message()
{
Console.WriteLine("MyDerivedClass");
}
}
若还要彻底去除父类方法的实现,则应使用abstract关键字,代码如下:
public abstract class MyClass : IMsg
{
public abstract void Message();
}
若需要使子类的实现不可被其他更低层次子类重载,则需使用sealed关键字。
public class MyDerivedClass2 : MyClass
{
public sealed override void Message()
{
Console.WriteLine("MyDerivedClass");
}
}
此外还可通过在借口方法中,调用virtual声明的方法来实现,子类对接口方法的重载逻辑,同时还可获得父类统一行为的控制。代码如下:
public class MyClass2 : IMsg
{
protected virtual void OnMessage()
{
}
public void Message()
{
OnMessage();//可以用子类重载
Console.WriteLine("MyClass");//父类的统一控制
}
}
最后你还可以使用子类继承父类来是实现子类对接口的实现,代码如下:
public class DefaultMessageGenerator
{
public void Message()
{
Console.WriteLine("This is a default message");
}
}
public class AnotherMessageGenerator :DefaultMessageGenerator, IMsg
{
// No explicit Message() method needed. 这里就不用显示实现IMsg方法了,因为继承的父类已实现该方法
}
出处:http://www.cnblogs.com/haokaibo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。