认真CS丨接口

如果把接口比作一个合同(规定了你必须做什么,但没规定你怎么做),那么实现了这个合同的类就相当于履行合约的人。这个人必须补充上自己的方式实现接口内规定的所有条款


什么是接口?

接口是指定一组函数成员(声明)而不实现他们的引用类型(方法),所以只能类和结构来实现接口


接口作用

using System;

class a
{
    public int a0;
}

class b
{
    public int b0;
}

class Program
{
    static void PrintInfo(a a1)
    {
        Console.WriteLine(a1.a0);
    }

    static void Main()
    {
        a ac = new a() { a0 = 10 };
        b bc = new b() { b0 = 20 };
        PrintInfo(ac);
    }
} 

这段代码很明显无法PrintInfo(bc),即PrintInfo类只能处理特定结构的类,那有没有办法让PrintInfo没有这个限制,能处理各种各样的类呢?接口将这个设想变为可能


接口实现的原理

接口仅声明方法名,不完成实现,由继承该接口的类完成实现。且我们在调用的方法参数列表里传入接口类型的方法,由于继承的类继承了该接口,继承的类也能传入,也就完成了该设想。也就是说只要继承类继承了该接口,无论该类内部什么结构,则都可以传入该方法

using System;

interface Ia
{
    string a0();
}

class b:Ia
{

    public string a0()
    {
        return "b0";
    }
}

struct c : Ia
{
    public string a0()
    {
        return "c0";
    }
    string c0()
    {
        return "cc0";
    }
}

class Program
{
    static void PrintInfo(Ia a1)
    {
        Console.WriteLine(a1.a0());
    }

    static void Main()
    {
        b ac = new b();
        c bc = new c();
        PrintInfo(ac);
        PrintInfo(bc);
    }
}


接口定义的条件

1、声明接口

a、接口声明不能包含以下成员:

数据成员:字段(int a...)、运算重载符、实例构造函数、析构函数

静态成员

b、接口声明只能包含如下类型的非静态成员函数声明:

方法

属性

事件

索引器


2、实现接口

只有类和结构才能实现接口,要实现接口,类或结构必须:

a、在基类列表中包含接口名称

b、为每一个接口的成员提供实现

c、实现接口的方法必须是公共的public

    接口中方法默认为public,且接口中修饰符不可改变,实现中方法默认private,所以需加public更改为公共的

注意:如果类从基类继承并实现了接口,基类列表中的基类名称必须放在所有接口之前

class Derived : MyBaseClass, IIfc1, IIfc2
{
    ...
}


接口是引用类型

接口不仅仅是类或结构要实现的成员列表,它是一个引用类型

我们不能直接通过类对象的成员访问接口(因为接口只有方法名,没有实现,并且下文会提到显、隐式实现,会出现方法名重名 的现象),我们只能通过把类对象强制转换成接口类型来获取指向接口的引用(类对象继承自接口,因为已经将继承类赋值给了接口的引用,所以调用对应接口的方法,会“看到”且实际调用继承类的成员),有了接口的引用,我们便可使用点号来调用接口方法

using System;

interface Ia
{
    void PrintInfo(string a1);
}

class b:Ia
{

    public void PrintInfo(string a1)
    {
        Console.WriteLine(a1);
    }

}

class Program
{
   
    static void Main()
    {
        b bc = new b();
        Ia ac = (Ia)bc;
        //上两句也可直接写为  Ia ac = new b();  
        ac.PrintInfo("I'm ac");
    }
}


接口和as运算符

如果我们尝试将类对象引用转换为接口的引用,若强制转换不成功则会抛出异常,as运算符可避免这个问题

a类对象引用转换为接口类型ILiveBirth

IliveBirth b = a as ILiveBirth;
if(b!=null)
    {
        ...
    }


实现多个接口

类或结构可以实现任意数量的接口

所有接口必须列在基类列表中,并以逗号分隔,如果有基类名称(例BaseB),则接口在基类之后

class b:BaseB,Ia,Ib
{
    ...
}


实现具有重复成员的接口

如果一个类实现了多个接口,并且其中一些接口有相同签名和返回值,那么类可以实现单个成员来满足所有重复成员的接口

interface Ia
{
    void PrintInfo(string a1);
}

interface Ib
{
    void PrintInfo(string a1);
}

class c:Ia,Ib
{

    public void PrintInfo(string a1)
    {
        Console.WriteLine(a1);
    }

}


多个接口的引用

即一个类实现了多个接口,那如何对不同接口内的方法进行调用?

在这我们仅讨论这个类实现的都是具有重复成员的接口

答:尽管接口内的成员相同,但接口名不同。我们声明不同的接口,对不同的接口进行调用,从而实现区分相同的方法名

using System;

interface Ia
{
    void PrintInfo(string a1);
}

interface Ib
{
    void PrintInfo(string a1);
}

class c:Ia,Ib
{

    public void PrintInfo(string a1)
    {
        Console.WriteLine(a1);
    }

}

class Program
{
    static void Main()
    {
        Ia a1 = new c();
        Ib b1 = new c();
        a1.PrintInfo("I'm a1");
        b1.PrintInfo("I'm b1");
    }
}


派生成员作为实现

即实现类是基类的派生,即实现类不仅继承了基类的接口,还可继承基类的方法

using System;

class st
{
public interface Ia
{
    void PrintInfo(string a1);
}

public interface Ib
{
    void PrintInfo(string a1);
}
}

class c:st
{
    class Iaa : Ia,Ib
    {
        public void PrintInfo(string a1)
        {
            Console.WriteLine(a1);
        }
    }
   
    class Program
    {
        static void Main()
        {
            Ia a1 = (Ia)new Iaa();
            Ib b1 = (Ib)new Iaa();
            a1.PrintInfo("I'm a1");
            b1.PrintInfo("I'm b1");
        }
    }
}


接口可继承接口

interface Ib:Ia
{
    ...
}


显示接口、隐式接口


实例:不同类都派生自一个基类且部分类实现一个接口,如何筛选出继承接口的类?

using System;

interface ILiveBirth
{
    string BabyCalled();
}

class Animal { }

class Cat : Animal, ILiveBirth
{
     public string BabyCalled()
    {
        return "kitten";
    }
}

class Dog : Animal, ILiveBirth
{
    public string BabyCalled()
    {
        return "puppy";
    }
}

class Bird : Animal
{

}

class Program
{
    static void Main()
    {
        Animal[] animalArray = new Animal[3];
        animalArray[0] = new Cat();
        animalArray[1] = new Dog();
        animalArray[2] = new Bird();

        foreach (Animal a in animalArray)
        {
            ILiveBirth b = a as ILiveBirth;
            if (b != null)
            {
                Console.WriteLine(b.BabyCalled());
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38239050/article/details/80147693
cs