* 说明:第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);
}
}