基础拾遗------接口详解

  接口定义了所有类继承接口时应遵循的契约。接口定义了 "要什么" ,派生类定义了 "怎么给" 。

 引用CLR VIA C#(类和接口继承)

  在Microsoft.Net Framwork中,有一个名为System.Object的类,它定义了4个公共实例方法:ToString, Equals, GetHashCode和GetType。该类是其他所有类的根或者说最终基类。换言之,所有类都继承了Object的4个实例方法。这还意味着能操作 Object类的实例的代码实际能操作任何类的实例。

  在CLR中,任何类都肯定从一个类也只能从一个类(而且只能从Objetc派生的类)派生的。这个类称为基类。基类提供了一组方法签名和这些方法的实现。你定义的新类可在将来由其它开发人员用作基类——所有方法签名和方法实现都会由新的派生类继承。

  CLR允许开发人员定义接口,它实际只是对一组方法签名进行了统一的命名。这些方法没有提供任何实现。类通过指定接口与名称来实现这个接口,它必须显式提供接口方法的实现,否则CLR会认为此类型定义无效。

类继承有一个重要特点,凡是能使用基类型实例的地方,都能使用派生类型的实例。类似的,凡是能使用具有接口类型实例的地方,都能使用实现了这个接口的一个类型的实例。

1.接口的特性

  1.1.接口是一个引用类型,通过接口可以实现多重继承。

  1.2.接口成员是自动公开的(public),且不能包含任何访问修饰符(public、protected、internal、private),否则 编译器会报错。

  1.3.接口类似于抽象基类,不能直接实例化接口;接口中的方法都是抽象方法,实现接口的任何非抽象类型都必须实现接口的所有成员:

   当显式实现该接口的成员时,实现的成员不能通过类实例访问,只能通过接口实例访问。

    当隐式实现该接口的成员时,实现的成员可以通过类实例访问,也可以通过接口实例访问,但是实现的成员必须是公有的。

  1.4.接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员,只能包含方法、属性、事件、索引等成员。

  1.5.接口成员不能有static、abstract、override、virtual修饰符,使用new修饰符不会报错,但会给出警告说不需要关键字new。

  1.6.在声明接口成员的时候,不准为接口成员编写具体的可执行代码,也就是说,只要在对接口进行声明时指明接口的成员名称和参数就可以了。

2.接口与抽象类

2.1下面让我们来对接口与抽象类做个对比。如有不同意见欢迎讨论。

interface

abstract class

实例化

不可以

不可以

派生类实现

必须实现所有契约

实现没实现的方法

继承

接口支持多继承

必须抽象类不能实现多继承

抽象

接口只能定义抽象规则

抽象类既可以定义规则,还可能提供已实现的成员。但不能使用new关键字,也不能被密封,原因是抽象类不能被实例化

概念

接口是一组行为规范

抽象类是一个不完全的类

回调

接口可以用于支持回调

抽象类不能实现回调,因为继承不支持

成员

接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法

抽象类可以定义字段、属性、包含有实现的方法

数据类型

接口可以作用于值类型和引用类型。例如,Struct就可以继承接口,而不能继承类

抽象类只能作用于引用类型

构造方法

没有构造方法

有构造方法

静态方法

没有静态方法(默认public static final类型)

包含静态方法

修饰符

默认public没有其他修饰符。

可以是public,protected

 2.2.抽象类和接口的使用:

2.2.1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本;

2.2.2.如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口;

2.2.3.如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类; 

2.2.4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。

3.接口声明

  3.1.接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的;

  3.2.根据约定,接口类型名称要以大写字母I开头;

public interface ITransactions
{
   // 接口成员
   void showTransaction();
   double getAmount();
}

注:3.3.对CLR而言,定义接口就像定义类型,也就是说,CLR会为接口类型对象定义一个内部数据结构,同时可用反射机制来查询接口类型的功能。

  3.4.为什么不能指定接口中方法的修饰符?

 接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。它们默认为公有方法。

4.接口的实现

 C#中的接口提供了一种实现运行时的多态。

 4.1.案例

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InterfaceApplication
{

   public interface ITransactions
   {
      // 接口成员
      void showTransaction();
      double getAmount();
   }
   public class Transaction : ITransactions
   {
      private string tCode;
      private string date;
      private double amount;
      public Transaction()
      {
         tCode = " ";
         date = " ";
         amount = 0.0;
      }
      public Transaction(string c, string d, double a)
      {
         tCode = c;
         date = d;
         amount = a;
      }
      public double getAmount()
      {
         return amount;
      }
      public void showTransaction()
      {
         Console.WriteLine("Transaction: {0}", tCode);
         Console.WriteLine("Date: {0}", date);
         Console.WriteLine("Amount: {0}", getAmount());

      }

   }
   class Tester
   {
      static void Main(string[] args)
      {
         Transaction t1 = new Transaction("001", "8/10/2012", 78900.00);
         Transaction t2 = new Transaction("002", "9/10/2012", 451900.00);
         t1.showTransaction();
         t2.showTransaction();
         Console.ReadKey();
      }
   }
}

  当上面的代码被编译和执行时,它会产生下列结果:

Transaction: 001
Date: 8/10/2012
Amount: 78900
Transaction: 002
Date: 9/10/2012
Amount: 451900

  4.2接口的隐式实现与显示实现

  4.2.1隐式实现

  interface IAnimal
    {
       void Dog();
    }
    class Animal:IAnimal
    {
      public void Dog()
      {
       //#
      }
     }
    //通过类调用
    Animal animal = new Animal();
    animal.Dog();
    //或者通过接口调用
    IAnimal animal = new Animal();
    animal.Dog();

以上:类与接口都能调用的为隐式实现。

  4.2.2.显示实现

interface IAnimal
  {
    void Dog();
  }
  class Animal:IAnimal
  {
    void IAnimal.Dog()
    {
      //#
    }
  }
IAnimal animal = new Animal();
animal.Dog();
Animal animal = new Animal();
(animal as IAnimal).Dog();

以上:用类的方法调用需要强制转换的实现为显示实现。

是不是感觉显示实现多余项目中也从来不曾遇到过???

  4.3.接口隐式实现,显示实现的场景

    4.3.1.当类实现一个接口时,通常使用隐式接口实现,这样可以方便的访问接口方法和类自身具有的方法和属性。

    4.3.2.当类实现多个接口时,并且接口中包含相同的方法签名,此时使用显式接口实现。即使没有相同的方法签名,仍推荐使用显式接口,因为可以标识出哪个方法属于哪个接口。

    4.3.3隐式接口实现,类和接口都可访问接口中方法。显式接口实现,只能通过接口访问。

5.接口的继承

5.1.接口继承和类继承不同:

    5.1.1.类继承不仅是说明继承,而且也是实现继承;而接口继承只是说明继承。

    5.1.2.C#中类继承只允许单继承,但是接口继承允许多继承,一个子接口可以有多个父接口(用","分割)。

5.2.接口的继承也形成接口之间的层次结构

 interface IProgram
    {
        void Fun();
    }
    interface IAProgram:IProgram
    {
        
    }
    class Program :  IAProgram
    {
        void IProgram.Fun()
        {
            Console.WriteLine("I am IProgram Fun.");
        }
        staticvoid Main(string[] args)
        {
            Program pro =new Program();
            ((IAProgram)pro).Fun();
            Console.Read();
        }
    }

6.接口的覆盖

  通过接口,可以指定组件必须实现的方法,但不实际指定如何实现方法。抽象类可以创建行为的定义,同时提供用于继承类的一些公共实现。对于在组件中实现多态行为,接口和抽象类都是很有用的工具。

  现在我们把一个抽象类被允许把接口方法映射到抽象方法中:

interface ICompute
    {
        void Add();
        void Subtract();
    }

abstract class Compute  : ICompute
{
    void ICompute.Add() { ComputeAdd(); }
    void ICompute.Subtract() { ComputeSubtract(); }
    protected abstract void ComputeAdd();
    protected abstract void ComputeSubtract();
}

  这里,从Compute派生的非抽象类要覆盖ComputeAdd和 ComputeSubtract, 因此提供了ICompute的实际实现程序。

7.接口泛型

 不多说:基础拾忆------泛型详解

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mukekeheart的iOS之旅

OC学习6——面相对象的三大特性

我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这也是面向对象的三大特征。OC学习篇之---类的三大特性(封装,继承,多态) 1、封装(Enca...

2708
来自专栏小勇DW3

Java之static作用的全方位总结

 引用一位网友的话,说的非常好,如果别人问你static的作用;如果你说静态修饰 类的属性 和 类的方法 别人认为你是合格的;如果是说 可以构成 静态代码块,...

902
来自专栏java学习

面试题39(关于继承的理解)

A派生出子类B,B派生出子类C,并且在java源代码中有如下声明? ---- A a0=new A( ); A a1=new B( ); A a2=new C...

3367
来自专栏PHP技术

javascript

1.创建Object实例两种方式。 var obj=new Object(); obj.name='zhangsan'; 第二种方式:使用对象字面量表示法。 v...

29110
来自专栏精讲JAVA

粗浅看 Java 反射机制

Java 反射是 Java 被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运 行时透过 Reflection APIs 取得任何一个已知名称的cl...

3246
来自专栏Micro_awake web

JavaScript OOP(三):prototype原型对象(即构造函数的prototype属性)

通过构造函数生成的实例化对象,无法共享属性或方法(即每个实例化对象上都有构造函数中的属性和方法);造成了一定的资源浪费 1 function Obj(name...

1927
来自专栏Script Boy (CN-SIMO)

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

场景:eclipse中编写java中用到数组 问题:       程序不报错但是运行过程中 终止,显示字样 “ Exception in thread "...

1830
来自专栏技术博客

编写高质量代码改善C#程序的157个建议[正确操作字符串、使用默认转型方法、却别对待强制转换与as和is]

  字符串应该是所有编程语言中使用最频繁的一种基础数据类型。如果使用不慎,我们就会为一次字符串的操作所带来的额外性能开销而付出代价。本条建议将从两个方面来探讨如...

894
来自专栏Janti

Java基础巩固——反射

什么是反射 ----    反射机制就是指程序运行时能够获取自身的信息。在Java中,只要给出类的名字,就可以通过反射机制来获取类的信息 哪里用的到反射机制 -...

2807
来自专栏java达人

Java运行时多态性:继承和接口的实现

image.png Java是面向对象的语言,而运行时多态性是面向对象程序设计代码重用的一个最强大机制,动态性的概念也可以被说成“一个接口,多个方法”。Ja...

2185

扫码关注云+社区