C#-接口interface
接口介绍
接口就是包含一组方法声明而没有定义的类型,接口是引用类型。
C#中的接口非常类似于C++中的抽象类,包含一些纯虚函数,只有方法的声明,没有实现。需要派生类来继承它,并实接口中的方法。
一个简单的接口使用示例:
using Custom;
//主函数
void Main()
{
CustomA objA = new CustomA();
CustomB objB = new CustomB();
test(objA);
test(objB);
}
//在这里以接口类型传入参数
void test(ICustomIfc obj)
{
obj.Add();
obj.Remove();
}
namespace Custom
{
//自定义接口
interface ICustomIfc
{
public void Add();
public void Remove();
}
//自定义类A,继承接口
class CustomA : ICustomIfc
{
public void Add()
{
Console.WriteLine("CustomA Add");
}
void ICustomIfc.Remove()
{
Console.WriteLine("CustomA Remove");
}
}
//自定义类B,继承接口
class CustomB : ICustomIfc
{
public void Add()
{
Console.WriteLine("CustomB Add");
}
void ICustomIfc.Remove()
{
Console.WriteLine("CustomB Remove");
}
}
}//namespace
输出:
CustomA Add
CustomA Remove
CustomB Add
CustomB Remove
接口的类型、存储和作用
接口类型和类类型一样,都是引用类型,也就是说一个接口变量(一般叫接口引用)和类对象一样,其实只是一个引用,存储在栈中;而真正的数据是存储在堆中。
代码示例:
//三种从类对象转为接口引用的方式
//主函数
void Main()
{
CustomA objA = new CustomA();
objA.Add();
//隐式转换
ICustomIfc ifc1 = objA;
ifc1.Add();
//显示转换
ICustomIfc ifc2 = (ICustomIfc)objA;
ifc2.Add();
//使用as运算符转换,实际中我们要使用as来转,这样更安全
//其他转换错误时会抛出异常,异常多了会严重降低代码执行速度
//as运算符转换错了会返回null,不会报异常
ICustomIfc ifc3 = objA as ICustomIfc;
ifc3?.Add(); //或者使用if判断,但这样更简洁
}
存储接口图:
作用:
统一类型,实现与类型无关的程序。以下只是我了解到的应用场景,可能还有很多其他的。
1、应用于函数参数,让方法的参数能够与类型无关,也就是一个类型的参数,能兼容好几种类型
2、应用于普通的对象调用方法,实现多态,使用接口引用调用不同派生类的同一个方法。
接口声明
接口可以声明以下非静态成员,并且可以不用加访问修饰符,默认都是public的,不能用private和protect修饰。
- 方法成员
- 属性成员
- 事件成员
- 索引器
代码示例:
//自定义接口, 接口名称不以I开头不会报错,但是按照惯例都会以I开头
//接口声明可以使用public、protected、internal和private修饰
public interface ICustomIfc
{
//int val = 10; //错误,不能包含字段
int Prop {get; set;} //可以包含属性
public void Add();
public void Remove();
double func1(); //不加修饰符默认为public
//private double func2(); //错误,不能包含私有或保护方法
//public static void func3(); //错误,不能包含静态方法
public delegate void MyDel(int param); //可以包含委托类型,子类不用实现
public event MyDel MyEvent; //可以包含事件成员,且子类必须实现
//可以有方法实现,编译不会报错
private double func2()
{
return 2;
}
}
//继承接口
class CustomA : ICustomIfc
{
public event ICustomIfc.MyDel MyEvent; //实现接口事件成员
public void Add()
{
Console.WriteLine("CustomA Add");
}
void ICustomIfc.Remove()
{
Console.WriteLine("CustomA Remove");
}
public double func1()
{
Console.WriteLine("CustomA func1");
return 0;
}
}
接口实现
接口的派生可以是类和结构体(C#中叫结构),如果继承了一个接口,必须实现他的所有成员,即允许接口声明的方法、属性、事件成员和索引器。一个类只能有一个基类,但可以继承多个接口,并且基类必须要放在所有的接口前面。
对于继承多个接口,如果两个接口中有相同的方法声明,可以实现一个类级别成员对应两个接口中的声明,
也可以使用显示接口成员来分别实现,但是这种方式实现的成员不能被类中内部方法调用,也不能在类外被直接调用,必须转换然后使用对应接口的引用来调用。
对于显示接口成员实现方式,虽然显示实现的方法定义在继承类中,但是属于对应的接口,而不属于类;对于类级别实现的成员方法,同时属于对应的接口和类,更准确说类和接口的同名方法使用了同一份方法(函数)定义。
代码示例:
//主函数
void Main()
{
//接口1调用自己的显示接口成员实现
ICustomIfc1 obj1 = new MyClass();
obj1.PrintOut();
//接口2没有显示接口成员实现,调的是类级别成员实现
ICustomIfc2 obj2 = new MyClass();
obj2.PrintOut();
//调用类级别实现
MyClass obj3 = new MyClass();
obj3.PrintOut();
//显示强转没什么意义(其实和上面隐式转换一样),调用的还是子类实现接口1的方法
ICustomIfc1 obj4 = (ICustomIfc1)obj3;
obj4.PrintOut();
//显示实现接口成员不能被直接调用,会编译不过,只能转为接口调用
MyClass obj5 = new MyClass();
//obj3.Ifc1Fun(); //错误
((ICustomIfc1)obj3).Ifc1Fun();
}
namespace Custom
{
//接口1
interface ICustomIfc1
{
public void PrintOut();
public void Ifc1Fun();
}
//接口2
interface ICustomIfc2
{
public void PrintOut();
}
//基类
class Base
{
}
//派生类继承多个接口
class MyClass : Base, ICustomIfc1, ICustomIfc2
{
//显示接口成员实现方式
//实现接口1的方法,注意前面不能用public修饰,会编译不过
void ICustomIfc1.PrintOut()
{
Console.WriteLine("实现接口1的方法");
}
/*
//显示实现接口2的方法
void ICustomIfc2.PrintOut()
{
Console.WriteLine("实现接口2的方法");
}
*/
//类级别成员实现方式,此方法会同时作为两个接口的实现方法
public void PrintOut()
{
Console.WriteLine("同时实现两个接口的方法");
}
//显示接口成员实现方式
void ICustomIfc1.Ifc1Fun()
{
Console.WriteLine("同时实现两个接口的方法");
}
void Func()
{
//显示接口成员实现不能直接被调用,编译不过,只能转为接口调用
//Ifc1Fun(); //错误
((ICustomIfc1)this).Ifc1Fun();
}
}//class
}//namespace
输出:
实现接口1的方法
同时实现两个接口的方法
同时实现两个接口的方法
实现接口1的方法
同时实现两个接口的方法
接口继承其他接口
一个接口可以继承其他的接口,只要把其他的接口放到基接口列表中即可
代码示例:
interface Ifc1
{
void Fun1();
}
interface Ifc2
{
void Fun2();
}
//继承两个接口
interface IMyIfc : Ifc1, Ifc2
{
void Fun3();
}
//继承接口后,要实现所有接口的方法
class MuClass : IMyIfc
{
public void Fun1()
{
}
public void Fun2()
{
}
public void Fun3()
{
}
}
本文作者:韩白白zz
本文链接:https://www.cnblogs.com/hanbaibai/p/16192555.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?