C#基础-第13章:接口
* 说明:第2部分:第13章:接口(259) * 13.1 本章内容: · 类和接口继承 · 定义接口 · 继承接口 · 关于调用接口方法的更多讨论 · 隐式和显示接口方法的实现 · 泛型接口 · 实现多个具有相同方法和签名的接口 · 用显式接口方法实现来增强编译时类型安全性 · 谨慎使用显示接口方法实现 · 设计:基类还是接口?
/* ============================================================================== ============================================================================== */ #define EIMITypeSafety_Version3 #define EIMINoBaseCall_Version2 #if !DEBUG #pragma warning disable 219 #endif using System; public static class Interfaces { public static void Main() { ImplementingAnInterface.Go(); InterfaceReimplementation.Go(); ExplicitInterfaceMethodImpl.Go(); GenericsAndInterfaces.Go(); UsingEIMI.Go(); EIMITypeSafety.Go(); EIMINoBaseCall.Go(); } } //////////////// 继承接口 Demo //////////////////////////////////// internal static class ImplementingAnInterface //P261 { public static void Go() { Point[] points = new Point[] { new Point(3, 3), new Point(1, 2), }; if (points[0].CompareTo(points[1]) > 0) { Point tempPoint = points[0]; points[0] = points[1]; points[1] = tempPoint; } Console.WriteLine("Points from closest to (0, 0) to farthest:"); foreach (Point p in points) Console.WriteLine(p); } // Point 从System.Object派生,并实现了IComparable<T> public sealed class Point : IComparable<Point> { private Int32 m_x, m_y; public Point(Int32 x, Int32 y) { m_x = x; m_y = y; } // 该方法为Point实现 IComparable<T>.CompareTo() public Int32 CompareTo(Point other) { return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y) - Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y)); } public override String ToString() { return String.Format("({0}, {1})", m_x, m_y); } } } /// <summary> /// 派生类不能重写sealed的接口方法的另外实现。见P262 /// </summary> internal static class InterfaceReimplementation// { public static void Go() { /************************* 第一个例子 *************************/ Base b = new Base(); // 用b的类型来调用Dispose,显示 "Base's Dispose" b.Dispose(); // 用b的对象的类型来调用 Dispose ((IDisposable)b).Dispose(); /************************* 第二个例子 ************************/ Derived d = new Derived(); // 用d的类型来调用Dispose显示 "Derived's Dispose" d.Dispose(); // 用d的对象的类型调用Dispose,显示: "Derived's Dispose" ((IDisposable)d).Dispose(); /************************* 第三个例子 *************************/ b = new Derived(); // 用b的类型来调用Dispose显示: "Base's Dispose" b.Dispose(); // 用b的对象的类型调用Dispose,显示: "Derived's Dispose" ((IDisposable)b).Dispose(); } // 这个类派生自Object,它实现了IDispoable internal class Base : IDisposable { // 这个方法隐式密封,不能被重写 public void Dispose() { Console.WriteLine("Base's Dispose"); } } // 这个类派生自Base,它重新实现了IDispoable internal class Derived : Base, IDisposable { //这个方法不能重写Base的Dispose //'new'表明该方法重新实现了IDisposable的Dispose方法 new public void Dispose() { Console.WriteLine("Derived's Dispose"); // 注意: 下面这个行代码展示了如何调用基类的实现(如果需要的话) // base.Dispose(); } } } /// <summary> /// 隐式和显式接口方法的实现 P264 /// </summary> internal static class ExplicitInterfaceMethodImpl { public static void Go() { SimpleType st = new SimpleType(); // 调用公共Dispose方法实现 st.Dispose(); // 调用 IDisposable 的 Dispose 方法的实现 IDisposable d = st; d.Dispose(); } public sealed class SimpleType : IDisposable //265 { #if false public void Dispose() { Console.WriteLine("Dispose"); } #else public void Dispose() { Console.WriteLine("public Dispose"); } void IDisposable.Dispose() { Console.WriteLine("IDisposable Dispose"); } #endif } } /// <summary> /// 泛型接口 P266 /// </summary> internal static class GenericsAndInterfaces { public static void Go() { Number n = new Number(); // Here, I compare the value in n with an Int32 (5) IComparable<Int32> cInt32 = n; Int32 result = cInt32.CompareTo(5); // Here, I compare the value in n with a String ("5") IComparable<String> cString = n; result = cString.CompareTo("5"); } // 该类实现泛型IComparable<T>接口两次 public sealed class Number : IComparable<Int32>, IComparable<String> { private Int32 m_val = 5; // 该方法实现 IComparable<Int32> 的CompareTo public Int32 CompareTo(Int32 n) { return m_val.CompareTo(n); } // 该方法实现 IComparable<String>的CompareTo public Int32 CompareTo(String s) { return m_val.CompareTo(Int32.Parse(s)); } } private static void SomeMethod1() { Int32 x = 1, y = 2; IComparable c = x; // CompareTo 期待 Object; 传递一个 y (一个 Int32)没有问题 c.CompareTo(y); // y在这里装箱 // CompareTo 期待Object; 传递 "2" (一个 String) 可以编译 // 但是运行时抛出ArgumentException异常 c.CompareTo("2"); } private static void SomeMethod2() { Int32 x = 1, y = 2; IComparable<Int32> c = x; // CompareTo 期待 Object; 传递一个 y (一个 Int32)没有问题 c.CompareTo(y); // y在这里不装箱 // CompareTo 期待Object; 传递 "2" (一个 String) 可以编译 // 指出String不能为转为Int32 // c.CompareTo("2"); } /// <summary> /// 泛型和接口的约束 /// </summary> public sealed class SomeType { private static void Test() { Int32 x = 5; // 对M的调用能通过编译,因为Int32实现了IComparable AND IConvertible M(x); // 这个M调用导致编译错误,因为GUID虽然实现了IComparable // 但是没有实现IConvertibles Guid g = new Guid(); // M(g); //这里会报错 } private static Int32 M<T>(T t) where T : IComparable, IConvertible { // ... return 0; } } } /// <summary> /// 实现多个具有相同方法名和签名的接口 /// </summary> internal static class UsingEIMI { public static void Go() { MarioPizzeria mp = new MarioPizzeria(); // 这里调用的MarioPizzeria的公共方法 mp.GetMenu(); // 下面代码调用的 MarioPizzeria的IWindow.GetMenu 方法 IWindow window = mp; window.GetMenu(); // 下面代码调用的 MarioPizzeria的 IRestaurant.GetMenu 方法 IRestaurant restaurant = mp; restaurant.GetMenu(); } public interface IWindow { Object GetMenu(); } public interface IRestaurant { Object GetMenu(); } // 这个类型派生自 System.Object 并 // 实现了 IWindow 和 IRestaurant 接口. public class MarioPizzeria : IWindow, IRestaurant { // 这个是IWindows 的 GetMenu() 实现 Object IWindow.GetMenu() { // ... return null; } // 这个是 IRestaurant’s GetMenu 方法的实现. Object IRestaurant.GetMenu() { // ... return null; } // 这个是GetMenu方法是可以选的,与接口无关 // to do with an interface. public Object GetMenu() { // ... return null; } } } public static class EIMITypeSafety { internal struct SomeValueType : IComparable { private Int32 m_x; public SomeValueType(Int32 x) { m_x = x; } #if EIMITypeSafety_Version1 public Int32 CompareTo(Object other) { return (m_x - ((SomeValueType)other).m_x); } #else public Int32 CompareTo(SomeValueType other) { return (m_x - other.m_x); } // NOTE: No public/private used on the next line Int32 IComparable.CompareTo(Object other) { return CompareTo((SomeValueType)other); } #endif } public static void Go() { #if EIMITypeSafety_Version1 SomeValueType v = new SomeValueType(0); Object o = new Object(); Int32 n = v.CompareTo(v); // Undesired boxing n = v.CompareTo(o); // InvalidCastException #endif #if EIMITypeSafety_Version2 SomeValueType v = new SomeValueType(0); Object o = new Object(); Int32 n = v.CompareTo(v); // No boxing n = v.CompareTo(o); // compile-time error #endif #if EIMITypeSafety_Version3 SomeValueType v = new SomeValueType(0); IComparable c = v; // Boxing! Object o = new Object(); Int32 n = c.CompareTo(v); // Undesired boxing n = c.CompareTo(o); // InvalidCastException #endif } } internal static class EIMINoBaseCall { #if EIMINoBaseCall_Version1 internal class Base : IComparable { // Explicit Interface Method Implementation Int32 IComparable.CompareTo(Object o) { Console.WriteLine("Base's CompareTo"); return 0; } } internal class Derived : Base, IComparable { // A public method that is also the interface implementation public Int32 CompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); // This attempt to call the base class's EIMI causes a compiler error: // error CS0117: 'Base' does not contain a definition for 'CompareTo' base.CompareTo(o); return 0; } } #endif #if EIMINoBaseCall_Version2 internal class Base : IComparable { // Explicit Interface Method Implementation Int32 IComparable.CompareTo(Object o) { Console.WriteLine("Base's IComparable CompareTo"); return CompareTo(o); // This now calls the virtual method } // Virtual method for derived classes (this method could have any name) public virtual Int32 CompareTo(Object o) { Console.WriteLine("Base's virtual CompareTo"); return 0; } } internal class Derived : Base, IComparable { // A public method that is also the interface implementation public override Int32 CompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); // Now, we can call Base's virtual method base.CompareTo(o); return 0; } } #endif public static void Go() { Derived d = new Derived(); d.CompareTo(null); } }