02011602 接口02-接口成员实现的3种方式、接口的继承
02011602 接口02-接口成员实现的3种方式、接口的继承
1. 实现多个接口
- 类可以实现任意数量的接口
- 所有实现的接口必须在基类列表中以逗号分隔(如果有基类名称,则接口在基类名称后面)
interface IDataRetrieve {int GetData();} // 声明接口1
interface IDataStore {void SetData(int x);} // 声明接口2
class MyData : IDataRetrieve, IDataStore // 声明类
{
int Mem1; // 声明字段
public int GetData() {return Mem1;} // 实现接口1中的所有成员
public void SetData(int x) {Mem = x;} // 实现接口2中的所有成员
}
2. 实现具有重复成员的接口
// 两个或多个接口成员具有相同的签名和返回类型
interface IIfc1 {void PrintOut(string s)}
interface IIfc2 {void PrintOut(string s)}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 两个或多个接口的单一实现
class MyClass : IIfc1, IIfc2 // 类可以实现任意数量的接口
{
public void PrintOut(sting s) // 单一实现
{
Console.WriteLine($"{s}")
}
}
说明:如果一个类实现了多个接口,并且其中一些接口成员具有相同的签名和返回类型,那么类可以实现单个函数成员来满足所有包含重复成员的接口。
3. 多个接口的引用
分离类中不同接口的引用
// 如果类实现了多个接口,我们可以获取每一个接口的独立引用。
using System;
namespace Demo01
{
interface IIfc1
{
void PrintOut(string s);
}
interface IIfc2
{
void PrintOut(string s);
}
class MyClass : IIfc1, IIfc2
{
public void PrintOut(string s)
{
Console.WriteLine($"Calling through:{s}");
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
mc.PrintOut("object"); // 从类对象调用
IIfc1 ifc01 = (IIfc1)mc; // 显式转换,获取IIfc1的引用
IIfc2 ifc02 = (IIfc2)mc; // 显式转换,获取IIfc2的引用
ifc01.PrintOut("interface1"); // 从IIfc1调用
ifc02.PrintOut("interface2"); // 从IIfc2调用
Console.ReadLine();
}
}
}
控制台输出:
Calling through:object
Calling through:interface1
Calling through:interface2
4. 派生成员作为实现
// 实现接口的类可以从它的基类继承实现的代码
interface IIfc1 {void PrintOut(string s)} // @1 声明接口
class MyBaseClass // @2 基类声明方法,但是没有实现接口
{
public void PrintOut(string s)
{
Console.WriteLine($"Calling through {s}");
}
}
class Derived : MyBaseClass, IIfc1 // @3 基类通过继承基类的方法实现接口
{
}
说明:
1. IIfc1是一个具有PrintOut方法成员的接口。
2. 基类包含一个PrintOut的方法,这个方法和接口的方法声明相匹配。
3. 派生类有一个空的声明主体,但是它派生自MyBaseClass,并在基类列表中包含了IIfc1。
4. 即使Derived的声明主体时空的,基类中的代码还是能满足实现接口方法的需求。
5. 显式接口成员实现
5.1 显式接口成员实现的引入
- 在第2小结中,演示的是接口成员的单一实现。如果我们希望为每一个接口成员分离实现怎么做呢?
- 可以创建显式接口成员实现。
- 显式接口成员实现有如下特性
- 与所有接口实现相似,显式接口成员实现在类或结构中。
- 显式接口实现使用限定接口名称来声明,由接口名称和成员名称以及它们中间的“.”分隔符号构成。
// 两个或多个接口成员具有相同的签名和返回类型
interface IIfc1 {void PrintOut(string s)}
interface IIfc2 {void PrintOut(string s)}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 显式接口实现
class MyClass : IIfc1, IIfc2
{
限定接口名称
↓
void IIfc1.PrintOut(string s) {...} // 显式实现
void IIfc2.PrintOut(string s) {...} // 显式实现
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
namespace Demo01
{
interface IIfc1
{
void PrintOut(string s);
}
interface IIfc2
{
void PrintOut(string s);
}
class MyClass : IIfc1, IIfc2
{
void IIfc1.PrintOut(string s)
{
Console.WriteLine($"IIfc1: {s}");
}
void IIfc2.PrintOut(string s)
{
Console.WriteLine($"IIfc2: {s}");
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
// mc.PrintOut("object"); // 错误写法,没有类级别的成员方法。
IIfc1 ifc01 = (IIfc1)mc;
IIfc2 ifc02 = (IIfc2)mc;
ifc01.PrintOut("interface1");
ifc02.PrintOut("interface2");
Console.ReadLine();
}
}
}
控制台输出:
IIfc1: interface1
IIfc2: interface2
说明:
1. 上述代码没有类级别的实现,无法通过对象直接调用方法。
2. 如果有显示接口成员实现,类级别的实现是允许的,但不是必须的。显式实现满足了类或结构必须实现方法的需求。
5.2 接口的三种实现场景总结
- 类级别实现
- 显式接口成员实现
- 类级别和显式接口成员实现
5.3 访问显式接口成员实现
// 显式接口成员实现只可以通过指向接口的引用来访问
interface IIfc1 {void PrintOut(string s)}
class MyClass : IIfc1
{
void IIfc1.PrintOut(string s)
{
Console.WriteLine("IIfc1")
}
public void Method()
{
PrintOut("...") // 编译错误
this.PrintOut("...") // 编译错误
((IIfc1)this).PrintOut("...") // 调用显式接口成员实现的方法
}
}
说明:这个限制对继承产生了重要的影响。由于其它类成员不能直接访问显式接口成员实现,派生类的成员也不能直接访问它们。
6. 接口的继承
- 接口可以继承接口。在4小结中已经演示了接口实现可以从基类被继承,此外接口本身可以从一个或多个接口继承而来。
- 要指定某个接口继承其它的接口,应在接口声明中把基接口以“.”分隔的列表形式放在接口名称后面的冒号之后。
// 接口继承的语法格式
派生接口名称 基类接口列表
↓ ↓
interface IDateIO : IDataRetrieve, IDataStore
{
...
}
注意,派生类的基类列表只能有一个类名,而派生接口在基接口列表中有任意多个接口。
1. 列表中的接口本身可以继承其它接口。
2. 派生接口包含它自身声明的所有成员和基接口的所有成员。
结尾
书籍:C#图解教程
著:【美】丹尼尔 · 索利斯;卡尔 · 施罗坦博尔
译:窦衍森;姚琪琳
ISBN:978-7-115-51918-4
版次:第5版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

浙公网安备 33010602011771号