写在前面的话: 编程
写到这一节的时候,CLR设计类型就已经结束了,由于CLR要求的是有必定基础的人看的,因此咱们不是从基础类型以及运算符开始的,文章从一开始就讲的是深刻面向对象编程,研究C#程序的设计模式。C#面向对象编程有三个特色:封装,继承,多态。接口的实现就是实现继承设计模式
其实在开始以前说一下这两天发生的事情,前几天维护项目代码时,虽然是本身写得可是因为逻辑判断比较多,有些变量名起的也不是颇有意义,在看的时候就彻底忘记当初为啥要写成这样了,也是有点汗颜,因此最近就把代码整洁之道也放在了看书的目录上,从此的示例代码也会符合代码整洁之道上的一些要求去写。而不是用无心义的a,b,c去作为变量名。安全
接口定义:ide
那么接口要作的事,也是让代码更加简洁的事情,接口定义了全部类继承接口时应遵循的语法合同。接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么作" 部分。接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。ui
说了这么多,那么咱们用接口实现一个计算器的例子,经过这个例子来讲明接口究竟是如何定义,如何使用的。先看接口的定义:spa
1 interface ICalculator { 2 //一般接口命令以 I 字母开头,ICalculator 中文意思就是计算器接口 3 //这个接口规定了一个计算器要有基本的加减乘除运算方法 4 //加法 5 int Add(int x,int y); 6 //减法 7 int Reduce(int x, int y); 8 //乘法 9 int Ride(int x, int y); 10 //除法 11 int Except(int x, int y); 12 }
接口实现:设计
上面的代码很简单吧,在接口中不能声明静态方法,接口中的方法不能用可见性修饰符修饰,在来看这句话:接口定义了全部类继承接口时应遵循的语法合同,也就是接口先规定好了我要实现那些方法和行为,继承个人要实现(重写)个人全部方法,而且返回值要和我相同,参数也要和我相同。不然就是违反了合同,语法就会报出错误。有了合同,类如今就像是一个建筑包工头,我只须要按照你的约定作,你让我盖十层楼,我就盖十层楼。继承接口类以下:code
1 public class Calculator : ICalculator 2 { 3 //:表示继承了计算机接口 4 //实现接口中的加法 5 public int Add(int x, int y) { 6 int sum = x + y; 7 return sum; 8 } 9 //实现接口中的减法 10 public int Reduce(int x, int y) 11 { 12 int sum = x - y; 13 return sum; 14 } 15 //实现接口中的乘法 16 public int Ride(int x, int y) 17 { 18 int sum = x * y; 19 return sum; 20 } 21 //实现接口中的除法 22 public int Except(int x, int y) 23 { 24 int sum = x / y; 25 return sum; 26 } 27 }
接口调用: orm
继承类必须实现接口中的全部方法,而且不能静态类继承接口,这里实现了接口中得全部方法,继续用上一个例子,接口比如是一个承包方:会告诉你我要什么样的房子,房子的颜色和大小,继承类就是施工方,按照承包方的要求去盖房子,知道了房子大小就开始计算要买多少砖瓦水泥。那么实现了接口的类如何调用实现呢?和正常的类同样调用和实现:对象
1 static void Main(string[] args) 2 { 3 //实例化一个计算器 4 Calculator calculator1 = new Calculator(); 5 //输出计算器的实现 输出结果为3 6 Console.WriteLine(calculator1.Reduce(5, 2)); 7 }
这就是一个最简单的接口调用和实现。看了这么多,你可能以为使用接口不是更加麻烦了么?若是从基类中继承不是更加简单?这样还须要定义接口,而且接口中全部成员都必须实现其方法。代表上来看是这样的,那么全部东西都有其使用的场景,接口的出生也不是为了简单类而出生。C#和CLR所支持的泛型接口为开发人员提供了许多很是出色的功能,接下来咱们讨论一下泛型接口提供的一些好处
泛型接口
首先泛型接口提供了出色的编译时类型安全性,有的接口在定义的方法使用了object参数或object返回类型,在代码调用这些接口方法时,可传递任何类型的实例应用,但这一般不是咱们指望的,而且使用非泛型还会形成装箱拆箱操做,今天列举C#中另一个泛型接口IComparable,
1 public interface IComparable<in T> 2 { 3 // 4 // 摘要: 5 // 比较当前对象和同一类型的另外一对象。 6 // 7 // 参数: 8 // other: 9 // 与此对象进行比较的对象。 10 // 11 // 返回结果: 12 // 一个值,指示要比较的对象的相对顺序。返回值的含义以下:值含义小于零此对象小于 other 参数。零此对象等于 other。大于零此对象大于 other。 13 int CompareTo(T other); 14 }
这是进行大小比较的接口,接受的参数是泛型,而且泛型参数支持协变和逆变,更大程度的支持参数的灵活性,他展现了泛型接口的另一个好处,类能够实现一个接口若干次,只要每次使用不一样的类型参数,示例:
1 public sealed class Comparable:IComparable<int>,IComparable<string> 2 { 3 private int m_val=5; 4 //方法实现了IComparable<string>的CompareTo方法 5 public int CompareTo(string str) 6 { 7 return m_val.CompareTo(Convert.ToInt32(str)); 8 } 9 //方法实现了IComparable<string>的CompareTo方法 10 public int CompareTo(int number) 11 { 12 return m_val.CompareTo(number); 13 } 14 }
须要说明的是,上面的代码最终在return m_val.CompareTo(Convert.ToInt32(str));这里实际调用的元数据int的CompareTo方法,所以虽然能够接收不一样类型参数,但在比较的时候仍是要对泛型参数进行int转化,才能够实现int的CompareTo方法。
泛型接口还能够对自身进行约束,也称做接口约束,接口约束能够将泛型类型参数约束为多个接口,这样一来,传递的参数类型必须所有接口约束。初读这段话是否是很晕?什么是将泛型类型参数约束为多个接口?为何约束事后,传递的参数类型必须实现所有约束?所有约束指的是哪一些约束?
1 public static class SomeType { 2 private static void Test() { 3 int x = 6; 4 Guid g = new Guid(); 5 //能够经过 由于int继承了IComparable, IFormattable, IConvertible, IComparable<Int32>, IEquatable<Int32> 6 M(x); 7 //编译不能经过,由于GUID没有继承IConvertible 8 //public struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid> 9 M(g); 10 } 11 //M的类型参数T被约束为只支持同时实现了 12 //IComparable和IConvertible接口的类型 13 private static int M<T>(T t) where T : IComparable, IConvertible { 14 return 1; 15 } 16 }
上面的方法,就是将参数约束了指定的接口,而且只有实现被约束的接口才能经过编译,不然就会失败。这就是接口的泛型约束。
总结:类仍是接口?
首先类只能继承一个实现,而接口能够继承多个,若是多种对象类型都能作某事,就为它建立接口。
若是是简单的类型,那么就使用基类,基类实现了大量的功能,而且不用实现全部成员