目录
如果把接口比作一个合同(规定了你必须做什么,但没规定你怎么做),那么实现了这个合同的类就相当于履行合约的人。这个人必须补充上自己的方式实现接口内规定的所有条款
🟥 什么是接口?
接口是指定一组函数成员(声明)而不实现他们的引用类型(方法),所以只能类和结构来实现接口
🟧 接口作用
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);
}
}
🟩 接口定义的条件
2️⃣ 声明接口
a、接口声明不能包含以下成员:
数据成员:字段(int a...)、运算重载符、实例构造函数、析构函数
静态成员
b、接口声明只能包含如下类型的非静态成员函数声明:
方法
属性
事件
索引器
1️⃣ 实现接口
只有类和结构才能实现接口,要实现接口,类或结构必须:
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());
}
}
}
}
大家还有什么问题,欢迎在下方留言!
如果你有 技术的问题 或 项目开发
都可以加下方联系方式
和我聊一聊你的故事🧡