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※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

posted @ 2025-08-17 09:08  qinway  阅读(9)  评论(0)    收藏  举报