CLR不支持多继承(因而所有托管编程语言也不支持)。CLR只是通过接口提供了"缩水版"的多继承。
接口可以定义事件、无参属性、索引器,这些东西本质上都是方法,它们只是对语法的一种简化而已。接口不能定义构造器方法,不能定义实例字段。虽然CLR允许接口定义静态方法、静态字段、常量、静态构造器,但C#禁止接口定义这些静态成员。
对于一个接口方法(类继承接口所实现的方法)C#编译器要求接口方法标记为public,CLR要求接口方法标记为virtual(这样派生类可以重写该方法,如果没有显示标记virtual,将默认标记为virtual sealed(派生类将不能重写该方法))。
隐式接口方法和显示接口方法的实现
看以下代码:
internal class SimpleType:IDisposable
{
public void Dispose(){ Console.WriteLine("Dispose");}
}
以上看似只有一个方法(确实只有一个方法,呵呵),该方法是一个隐式接口方法。但在该类加载到CLR时,该类的方法表里指向这个方法的记录项却又两个,一个是接口方法的记录项,一个是新方法的记录项(因为这个方法的签名与IDisposable接口定义的Dispose()方法完全一致,且可访问性是public)
public class Program{
public static void Main(){
SimpleType st=new SimpleType();
st.Dispose(); //Dispose
IDisposable d=st;
d.Dispose(); //Dispose
}
}
看以上代码, st.Dispose()和d.Dispose()都指向同一个隐式接口方法
如果将SimpleType类写成如下:
internal class SimpleType:IDisposable
{
public void Dispose(){ Console.WriteLine("Dispose");}
void IDisposable.Dispose(){Console.WriteLine("IDispose");}
}
运行Main()方法的结果将是:
Dispose
IDispose
其中void IDisposable.Dispose(){Console.WriteLine("IDispose");}是显示接口方法,这样接口方法的记录项会指向该显示接口方法,而新方法的记录项会指向 public void Dispose(){ Console.WriteLine("Dispose");}
在C#中将定义方法的那个接口的名称作为方法名的前缀(如这里的 IDisposable.Dispose)称为显示接口方法实现(EIMI)。定义EIMI时不能指定可访问性,默认是private。要调用EIMI时只能通过接口类型的一个变量来进行。另外,EIMI不能标记为virtual,所以它不能被重写。
泛型接口有一个好处是类可以实现同一个接口若干次,只要每次使用不同的类型参数:
//该类实现了IComparable<T>接口两次
public class Number:IComparable<Int32>,IComparable<String>
{
private Int32 m_val=5;
public Int32 CompareTo(Int32 n)
{
return m_val.CompareTo(n);
}
public Int32 CompareTo(string s)
{
return m_val.CompareTo(Int32.Parse(s));
}
}
定义实现多个接口的一个类型时,这些接口有可能定义了具有相同名称和签名(返回值及参数)的方法:
public interface IWindow{
Object GetMenu();
}
public interface IRestaurant{
Object GetMenu();
}
要定义一个实现了以上俩接口的类型,必须用 显示接口方法实现:
public class MarioPizzeria:IWindow,IRestaurant
{ //这是IWindow的GetMenu()方法实现
Object IWindow.GetMenu(){...}
//这是IRestaurant的GetMenu()方法实现
Object IRestaurant.GetMenu(){...}
//这个GetMenu()方法是可选的,与接口无关
public Object GetMenu(){...}
}
未完待续...