第十三章 接口
2013-02-27
13.5 隐式和显示接口方法实现
1. 隐式接口的实现
2. 显示接口的实现
13.8 实现多个具有相同方法名和签名的接口
13.9 用显示接口类型方法实现来增强编译时类型安全
ToDo: 什么时候使用接口和什么时候使用类
13.5 隐式和显示接口方法实现
?显式接口和隐式接口的关系
1 class SimpleType : IDisposable 2 { 3 public void Dispose() { Console.WriteLine("Dispose"); } 4 } 5 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 SimpleType st = new SimpleType(); 11 //调用公共Dispose方法 12 st.Dispose(); 13 //调用IDisposable的Dispose方法 14 IDisposable d = st; 15 d.Dispose(); 16 } 17 }
上面调用的是同一个方法,输出都是:Dispose
1 class SimpleType : IDisposable 2 { 3 public void Dispose() { Console.WriteLine("public Dispose"); } 4 //显式调用 5 void IDisposable.Dispose() { Console.WriteLine("IDisposable.Dispose"); } 6 }
输出结果:
public Dispose
IDisposable.Dispose
注意:在C#定义一个显示接口方法是,不允许定义可访问性,编译器会设置其访问性为private。要调用它,只能通过接口类型的一个变量来进行。
13.8 实现多个具有相同方法名和签名的接口
有两个接口具有相同方法名和签名的方法,必须用“显示接口的方法实现”。
1 interface IWindow { object GetMenu();} 2 interface IRestaurant { object GetMenu();} 3 class Mario : IWindow, IRestaurant 4 { 5 object IWindow.GetMenu() { return null; } 6 object IRestaurant.GetMenu() { return null; } 7 }
13.9 用显示接口类型方法实现来增强编译时类型安全
如何接口的方法接受System.Object类型的参数或返回值时,就会丧失编译时的类型安全性,装箱也会发生,看如下代码:
1 struct SomeValueType : IComparable 2 { 3 private int _x; 4 public SomeValueType(int x) { _x = x; } 5 public int CompareTo(Object other) 6 { return (_x - ((SomeValueType)other)._x); } 7 } 8 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 SomeValueType v = new SomeValueType(0); 14 object o = new object(); 15 int n = v.CompareTo(v); //非预期装箱 16 n = v.CompareTo(o); //InvalidCastException异常 17 } 18 }
可做如下改动避免以上错误:
1 struct SomeValueType : IComparable 2 { 3 private int _x; 4 public SomeValueType(int x) { _x = x; } 5 public int CompareTo(SomeValueType other) //修改参数类型 6 { return (_x - other._x); } 7 int IComparable.CompareTo(Object other) //添加显示接口方法实现 8 { return CompareTo((SomeValueType)other); } 9 } 10 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 SomeValueType v = new SomeValueType(0); 16 object o = new object(); 17 int n = v.CompareTo(v); //没有装箱操作 18 n = v.CompareTo(o); //编译时就会报错 19 } 20 }
但如果定义一个接口类型变量还是会报错,看如下代码:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 SomeValueType v = new SomeValueType(0); 6 IComparable c = v; //装箱 7 object o = new object(); 8 int n = c.CompareTo(v); //非预期装箱 9 n = c.CompareTo(o); // InvalidCastException异常 10 } 11 }