1.1 C#中的类可以多继承吗?
在C#中申明一个类型时,只支持单继承(即继承一个父类),但支持实现多个接口(Java也是如此)。像C++可能会支持同时继承自多个父类,但.NET的设计小组认为这样的机制会带来一些弊端,并且没有必要。
首先,看看多继承有啥好处?多继承的好处是更加贴近地设计类型。例如,当为一个图形编辑器设计带文本框的矩形类型时,最方便的方法可能是这个类型既继承自文本框类型,又继承自矩形类型,这样它就天生地具有输入文本和绘画矩形的功能。But,自从C++使用多继承依赖,就一直存在一些弊端,其中最为严重的还是所谓的“砖石继承”带来的问题,下图解释了砖石继承问题。
如上图所示,砖石继承问题根源在于最终的子类从不同的父类中继承到了在它看来完全不同的两个成员,而事实上,这两个成员又来自同一个基类。鉴于此,在C#/Java中,多继承的机制已经被彻底抛弃,取而代之的是单继承和多接口实现的机制。众所周知,接口并不做任何实际的工作,但是却制定了接口和规范,它定义了特定的类型都需要“做什么”,而把“怎么做”留给实现它的具体类型去考虑。也正是因为接口具有很大的灵活性和抽象性,因此它在面向对象的程序设计中更加出色地完成了抽象的工作。
1.2 C#中重写、重载和隐藏是什么鬼?
在C#或其他面向对象语言中,重写、重载和隐藏的机制,是设计高可扩展性的面向对象程序的基础。
(1)重写和隐藏
重写(Override)是指子类用Override关键字重新实现定义在基类中的虚方法,并且在实际运行时根据对象类型来调用相应的方法。
隐藏则是指子类用new关键字重新实现定义在基类中的方法,但在实际运行时只能根据引用来调用相应的方法。
以下的代码说明了重写和隐藏的机制以及它们的区别:
public class Program { public static void Main(string[] args) { // 测试二者的功能 OverrideBase ob = new OverrideBase(); NewBase nb = new NewBase(); Console.WriteLine(ob.ToString() + ":" + ob.GetString()); Console.WriteLine(nb.ToString() + ":" + nb.GetString()); Console.WriteLine(); // 测试二者的区别 BaseClass obc = ob as BaseClass; BaseClass nbc = nb as BaseClass; Console.WriteLine(obc.ToString() + ":" + obc.GetString()); Console.WriteLine(nbc.ToString() + ":" + nbc.GetString()); Console.ReadKey(); } } // Base class public class BaseClass { public virtual string GetString() { return "我是基类"; } } // Override public class OverrideBase : BaseClass { public override string GetString() { return "我重写了基类"; } } // Hide public class NewBase : BaseClass { public new virtual string GetString() { return "我隐藏了基类"; } }