前言

接口定义了所有。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。

接口定义了属性、方法和事件,这些都是接口的成员。



接口提供了。

接口使得实现接口的类或结构体在形式上保持一致

接口和抽象类的理解:

抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时

接口本身并不实现任何功能,它只是和声明实现该接口的对象订立一个必须实现哪些行为的契约

抽象类不能直接实例化,但允许派生出具体的,具有实际功能的类。


一、定义接口

接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。下面是一个接口声明的实例:

interface IMyInterface
{
    void MethodToImplement();
}

以上代码定义了接口 IMyInterface。,这个接口只有一个方法 MethodToImplement(),没有参数和返回值,当然我们可以按照需求设置参数和返回值。

值得注意的是,。

二、实现接口

接下来我们来实现以上接口:InterfaceImplementer.cs

using System;

interface IMyInterface
{
        // 接口成员
    void MethodToImplement();
}

class InterfaceImplementer : IMyInterface
{
    static void Main()
    {
        InterfaceImplementer iImp = new InterfaceImplementer();
        iImp.MethodToImplement();
        Console.ReadLine();
    }

    public void MethodToImplement()
    {
        Console.WriteLine("MethodToImplement() called.");
    }
}

InterfaceImplementer 类实现了 IMyInterface 接口,接口的实现与类的继承语法格式类似:

class InterfaceImplementer : IMyInterface

继承接口后,我们需要实现接口的方法 MethodToImplement() , 。

三、接口继承

以下实例定义了两个接口 IMyInterface 和 IParentInterface。

如果一个接口继承其他接口,那么实现类或结构就需要实现所有接口的成员。

以下实例 IMyInterface 继承了 IParentInterface 接口,因此接口实现类必须实现 MethodToImplement() 和ParentInterfaceMethod() 方法:

using System;

interface IParentInterface
{
    void ParentInterfaceMethod();
}

interface IMyInterface : IParentInterface
{
    void MethodToImplement();
}

class InterfaceImplementer : IMyInterface
{
    static void Main()
    {
        InterfaceImplementer iImp = new InterfaceImplementer();
        iImp.MethodToImplement();
        iImp.ParentInterfaceMethod();
        Console.ReadLine();
    }

    public void MethodToImplement()
    {
        Console.WriteLine("MethodToImplement() called.");
    }

    public void ParentInterfaceMethod()
    {
        Console.WriteLine("ParentInterfaceMethod() called.");
    }
}

实例输出结果为:

MethodToImplement() called.
ParentInterfaceMethod() called.

总结

  • 接口的定义:指定一组函数成员而不实现成员的引用类型,其它类型和接口可以继承接口。
  • 接口是“是什么”的规范,继承类或结构体是“怎么做”的具体实现。
  • 接口的特点:见 补充:一、二
  • 接口的应用场景:见实例1来理解
  • 接口和抽象类的区别

补充

一、接口注意的几点:

  • 接口方法不能用public abstract等修饰。接口内不能有字段变量,构造函数。
  • 接口内可以定义属性(有get和set的方法)。如string color { get ; set ; }这种。
  • 实现接口时,必须和接口的格式一致。
  • 必须实现接口的所有方法。

二、接口的定义是指定一组函数成员而不实现成员的引用类型,其它类型和接口可以继承接口。接口主要有以下特点:

  1. 通过接口可以实现多重继承,C# 接口的成员不能有 public、protected、internal、private 等修饰符。原因很简单,接口里面的方法都需要由外面接口实现去实现方法体,那么。C# 接口中的成员默认是 public 的。
  2. 接口成员不能有 new、static、abstract、override、virtual 修饰符。有一点要注意,。
  3. 接口中只包含成员的签名,。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,,除非实现类本身是抽象类。
  4. C# 的类是单继承,接口是解决 C# 里面类可以同时继承多个基类的问题。

实例1:【加深接口的理解】

每个员工的属性、方法等都是相似的,这时就可以规范一个接口,而不是每个员工都搞个类。

class Program
{
    static void Main(string[] args)
    {
        IWorker james1 = new James1();
        IWorker james2 = new James2();
        james1.work("设计");
        james2.work("编程");
        //从这个例子我体会到了有接口的好处,可以想象如果又来了新的员工。
        //如果不采用接口,而是每个员工都有一个单独的类,这样就会容易出错。
        //如果有接口这种协议约束的话,那么只要实现了接口就肯定有接口里声明的方法,我们只需拿来调用。
        Console.ReadLine();
    }
}
public interface IWorker{ void work(string s); }
class James1 : IWorker
{
    public void work(string s)
    {
        Console.WriteLine("我的名字是James1,我的工作是" +s);
    }
}
class James2 : IWorker
{
    public void work(string s)
    {
        Console.WriteLine("我的名字是James2,我的工作是"+s);
    }
}

实例2【重要:结构体实现接口后是值类型还是引用类型?】

在C#中数据类型分为值类型和引用类型
值类型:结构体、枚举
引用类型:类、接口、数组、委托

在结构使用时,结构可以实现接口。这时就有一个问题“结构体实现接口后是值类型还是引用类型?”。带着这个问题,我们看下面这段代码。

using System;

namespace ConsoleApp1
{
    //结构体班级   
    struct StructClass : IClass
    {
        public int Count;//人数   
        public void AddStudent()
        {
            Count++;
        }

        public void ShowCount()
        {
            Console.WriteLine(Count);
        }

    }
    //接口   
    interface IClass
    {
        void AddStudent();//添加学生   
        void ShowCount();//显示学生人数   
    }
    class Program
    {
        static void Main(string[] args)
        {
            StructClass s1 = new StructClass();
            StructClass s2 = s1;
            s1.AddStudent();
            s1.ShowCount(); //输出1   
            s2.ShowCount(); //输出0   
            //说明s2和s1不指向同一个对象,s2=s1是创建了一个s1的副本 
            //这是值类型很显著的标志   

            IClass ic1 = new StructClass();
            IClass ic2 = ic1;
            ic1.AddStudent();
            ic1.ShowCount();//输出1   
            ic2.ShowCount();//输出1   
            //说明s2和s1指向同一个对象,s2=s1是将s1的引用赋给s2   
            //这是引用类型很显著的标志   
            Console.ReadLine();
        }
    }
}

运行结果:

1
0
1
1

最后得出结论:
当我们声明对象(s1、s2)是结构体类型时,对象是值类型,对象在栈中创建
当我们声明对象(ic1、ic2)是接口类型时,对象是引用类型,对象在堆中创建

06-30 14:37