一、接口的声明
接口是指定一组函数成员而不实现它们的引用类型。所以只能类和结构来实现接口。接口提出了一种规范,让使用接口的程序的必须严格遵守接口提出的约定。使用interface关键字进行定义,可由方法、属性、事件、索引器或这四种成员类型的任何组合构成。
接口声明的格式:
修饰符 interface 接口名称
{
接口内容;
}
备注:接口名称习惯以I开头,跟在I后的第一个字符也是大写,结尾一般以able结尾。
接口的特性:
- 接口中只能声明方法不能定义,也就是说声明的方法不能有方法体。
- 接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型,不能包含虚拟或静态成员。由于不能有字段,所以属性经常被写做自动属性。
- 接口可以有访问修饰符,但是接口成员不能包含任何访问修饰符。因为接口中的方法是用来定义对象之间通信的契约,所以指定接口中的方法为私有或保护没有意义。它们默认是公有方法。
- 接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。
- 接口可以继承其他接口,类可以通过其继承的基类(或接口)多次继承同一个基类。
- 接口类似于抽象基类,继承接口的任何类型都必须实现接口的所有成员。
- 接口中不能包括构造函数,因此不能直接实例化接口。
- 接口可以包含属性、方法、索引器和事件。
- 接口中只能定义成员,不能实现成员。
//简单接口的示例1~
using System;
namespace _20220807_1
{
interface IIfc1
{
void PrintOut(string s);
}
class Myclass : IIfc1
{
public void PrintOut(string s)
{
Console.WriteLine($"调用:{s}");
}
}
class Program
{
static void Main(string[] args)
{
Myclass mc = new Myclass();
mc.PrintOut("object");
}
}
}
二、接口的实现
实现接口的方式有两种:
1、当隐式实现该接口的方法时,既可以接口调用方法,也可以用具体类调用方法,但是实现的成员必须是公有的。
//简单接口的示例2~
using System;
namespace Project11
{
interface IPro
{
void Write();
}
class Myclass : IPro
{
//这里直接写方法,无需IPro.Write()
public void Write()//这里Write方法必须使用public继续修饰。
{
Console.WriteLine("隐式实现接口的方法");
}
}
class Program
{
static void Main(string[] args)
{
//实现的方法可以通过声明接口实例访问
IPro p1 = new Myclass();
p1.Write();
//也可以通过类实例化访问
Myclass p2 = new Myclass();
p2.Write();
}
}
}
2、当显式实现该接口的方法时,不能用访问修饰符public,并且必须显式指定接口名称。实现的成员不能通过类实例反问,只能通过接口实例访问。
继承接口后,用户需要实现接口的方法,并且方法名必须与接口定义的方法名一致。IProgram p1 = new MyClass();//声明一个接口实例,但不是对接口进行实例化。
using System;
namespace Project12
{
interface IProgram
{
void Write();
}
class MyClass : IProgram
{
//实现接口的方法,不能用public,并且必须显式指定接口名称这里是:接口名称.方法
void IProgram.Write()//这里
{
Console.WriteLine("显式实现接口的方法");
}
}
class Program
{
static void Main(string[] args)
{
IProgram p1 = new MyClass();//声明一个接口实例,但不是对接口进行实例化。
p1.Write();
//MyClass p2 = new MyClass();
}
}
}
3、使用的优缺点
一般情况下,当类或结构要实现的是单个接口,可以使用隐式实现。如果类或结构继承了多个接口且接口中具有相同名称成员时,就要用到显式实现。
由于显式接口成员属于接口的成员,而不是类的成员,所以不能使用类对象直接访问,只能通过接口对象来访问。
using System;
namespace _20220807_2
{
interface ImyInterface1
{
int add();
}
interface ImyInterface2
{
int add();
}
class myClass : ImyInterface1, ImyInterface2
{
int ImyInterface1.add() //显式接口的成员实现
{
int a = 9;
int b = 62;
return a + b;
}
int ImyInterface2.add() //显式接口的成员实现
{
int a = 41;
int b = 65;
int c = 101;
return a + b + c;
}
}
class Program
{
static void Main(string[] args)
{
myClass mc1 = new myClass();//实例化继承类的对象,该类继承了接口
ImyInterface1 imy1 = mc1; //使用继承接口类的对象 实例化接口
Console.WriteLine(imy1.add());//使用接口对象调用接口中的方法
ImyInterface2 imy2 = mc1; //使用继承接口类的对象实例化接口
Console.WriteLine(imy2.add());//使用接口调用方法
}
}
}
三、接口的继承
接口继承和类继承不同。首先,类继承不仅是说明继承,同时也是实现继承;而接口继承只是说明继承,即派生类可以继承基类的方法实现,而派生的接口只继承了父接口的成员方法说明,而没有继承父接口的实现,其次,C#中继承只允许单继承,但是接口继承允许多继承,一个子接口可以有多个父接口。
接口可以从零或多个接口中继承。从多个接口中继承时,用冒号“:”后跟被继承的接口名字,多个接口名之间用逗号“,”分隔。
接口的多重继承:在使用多重继承时,要继承的接口之间用逗号“,”分隔。
using System;
namespace Project14
{
interface IPeople
{
//由于不能有字段,所以属性经常被写作自动属性
string Name //声明Name属性
{
get;
set;
}
string Gender //声明Gender属性
{
get;
set;
}
}
interface ITeacher : IPeople
{
void teach();
}
interface IStudent : IPeople
{
void study();
}
class Program : IPeople, ITeacher, IStudent
{
string _name = "";
string _gender = "";
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public string Gender
{
get
{
return _gender;
}
set
{
_gender = value;
}
}
public void teach()
{
Console.WriteLine("大家好,我叫{0},我是{1}生,我是一名老师", Name, Gender);
}
public void study()
{
Console.WriteLine("大家好,我叫{0},我是{1}生,我是一名学生", Name, Gender);
}
static void Main(string[] args)
{
ITeacher iteach = new Program();
iteach.Name = "张三";
iteach.Gender = "男";
iteach.teach();
IStudent istu = new Program();
istu.Name = "李四";
istu.Gender = "女";
istu.study();
}
}
}
如果一个接口继承其它接口,那么实现类或结构就需要实现所有接口的成员。
using System;
namespace Project15
{
interface IFirst
{
void FirstMethod();
}
interface ISecond : IFirst
{
void SecondMethod();
}
class Program : ISecond
{
static void Main()
{
Program pro = new Program(); //实例化类的对象
IFirst first = pro; //使用派生类对象实例化接口IFirst
ISecond second = pro; //使用派生类对象实例化接口ISecond
first.FirstMethod();
second.SecondMethod();
}
public void FirstMethod()
{
Console.WriteLine("这里是第一个接口的方法");
}
public void SecondMethod()
{
Console.WriteLine("这里是第二个接口的方法");
}
}
}