zoukankan      html  css  js  c++  java
  • CLR设计类型之接口

    写在前面的话:            

            写到这一节的时候,CLR设计类型就已经结束了,因为CLR要求的是有一定基础的人看的,所以我们不是从基础类型以及运算符开始的,文章从一开始就讲的是深入面向对象编程,研究C#程序的设计模式。C#面向对象编程有三个特点:封装,继承,多态。接口的实现就是实现继承

               其实在开始之前说一下这两天发生的事情,前几天维护项目代码时,虽然是自己写得但是由于逻辑判断比较多,有些变量名起的也不是很有意义,在看的时候就完全忘记当初为啥要写成这样了,也是有点汗颜,所以最近就把代码整洁之道也放在了看书的目录上,今后的示例代码也会符合代码整洁之道上的一些要求去写。而不是用无意义的a,b,c去做为变量名。

    接口定义:

             那么接口要做的事,也是让代码更加简洁的事情,接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做" 部分。接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。

            说了这么多,那么我们用接口实现一个计算器的例子,通过这个例子来说明接口到底是如何定义,如何使用的。先看接口的定义:

     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     }
    View 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     }
    View Code

    接口调用: 

        继承类必须实现接口中的所有方法,并且不能静态类继承接口,这里实现了接口中得所有方法,继续用上一个例子,接口好比是一个承包方:会告诉你我要什么样的房子,房子的颜色和大小,继承类就是施工方,按照承包方的要求去盖房子,知道了房子大小就开始计算要买多少砖瓦水泥。那么实现了接口的类如何调用实现呢?和正常的类一样调用和实现:

    1     static void Main(string[] args)
    2         {
    3             //实例化一个计算器
    4             Calculator calculator1 = new Calculator();
    5             //输出计算器的实现  输出结果为3
    6             Console.WriteLine(calculator1.Reduce(5, 2));
    7         }
    View Code

            这就是一个最简单的接口调用和实现。看了这么多,你可能觉得使用接口不是更加麻烦了么?如果从基类中继承不是更加简单?这样还需要定义接口,并且接口中所有成员都必须实现其方法。表明上来看是这样的,那么所有东西都有其使用的场景,接口的出生也不是为了简单类而出生。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     }
    View Code

           这是进行大小比较的接口,接受的参数是泛型,并且泛型参数支持协变和逆变,更大程度的支持参数的灵活性,他展示了泛型接口的另外一个好处,类可以实现一个接口若干次,只要每次使用不同的类型参数,示例:

     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     }
    View Code

          需要说明的是,上面的代码最终在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     }
    View Code

          上面的方法,就是将参数约束了指定的接口,并且只有实现被约束的接口才能通过编译,否则就会失败。这就是接口的泛型约束。

    总结:类还是接口?

                 首先类只能继承一个实现,而接口可以继承多个,如果多种对象类型都能做某事,就为它创建接口。

                 如果是简单的类型,那么就使用基类,基类实现了大量的功能,并且不用实现所有成员

                  

                       

                     

               

               

      

  • 相关阅读:
    Algs4-1.3.44文本编辑器的缓冲区
    Algs4-1.3.42复制栈
    Algs4-1.3.41复制队列采用for方式实现
    Algs4-1.3.39环形缓冲区
    Algs4-1.3.40前移编码
    Algs4-1.3.38删除第k个元素-数组实现
    安全测试的一些漏洞和测试方法
    Java内存自动回收,为什么会有内存泄露?
    三款主流静态源代码安全检测工具比较
    Fortify源码安全检测工具
  • 原文地址:https://www.cnblogs.com/Demon-Su/p/7400299.html
Copyright © 2011-2022 走看看