当前位置: 首页 > news >正文

第16章 接口 笔记

第16章 接口 笔记 25.06.22

16.1 什么是接口

接口是声明一组函数成员,而不进行实现的引用类型,只能用类和结构来实现接口。

一个函数内不能传入多个类的实例做为参数,可以通过接口来实现。

// 声明接口
interface IInfo
{string GetName();string GetAge();
}// 声明实现接口的CA类
class CA:IInfo
{public string Name;public int Age;public string GetName() {return Name;}public string GetAge() {return Age.ToString();}
}class CB:IInfo
{public string First;public string Last;public double PersonsAge;public string GetName() {return First + " " + Last;}public string GetAge() {return PersonAge.ToString();}
}class Programe
{// 传入接口的引用static void PrintInfo(IInfo item){Console.WriteLine("Name: {0}, Age {1}", item.GetName(), item.GetAge());}static void Main(){CA a = new CA() {Name = "John Doe", Age = 35};CB b = new CB() { First = "Jane", Last = "Doe", PersonAge = 33};// 对象的引用自动转化为 它们实现的接口的引用PrintInfo(a);printInfo(b);}
}// outputName: John Doe, Age 35Name: Jane Doe, Age 33

使用 IComparable 接口的示例

整数数组排序

var myInt = new [] { 20, 4, 16, 9, 2 };    
Array.Sort(myInt);                         
foreach (var i in myInt)                   Console.Write($"{ i } ");// This code produces the following output
2 4 9 16 20

Array类的Sort方法无法对对象数组进行排序,它不知道如何比较对象以及如何进行排序。

Array 类的 Sort 方法依赖于 IComparable 接口,其声明在 BCL 中,只包含唯一的 CompareTo 方法,该方法目前未实现。

IComparable接口 示例

public interface IComparable
{int CompareTo( object obj );
}

调用 CompareTo 方法时,应该返回如下值:

  • 负数:当前对象 < 参数对象。

  • 正数:当前对象 > 参数对象。

  • 0:两个对象相等。

为自定义类实现 IComparable 接口后,就可以使用 Array.Sort 方法进行排序

要实现一个接口,类或结构必须做两件事:

在基类类别中列出接口的名称

为接口的每一个成员提供实现

// 类实现接口
class MyClass : IComparable
{public int TheValue;public int CompareTo(object obj)   // Implementation of interface method{MyClass mc = (MyClass)obj;if (this.TheValue < mc.TheValue) return -1;if (this.TheValue > mc.TheValue) return  1;return 0;}
}class Program {static void PrintOut(string s, MyClass[] mc){Console.Write(s);foreach (var m in mc)Console.Write($"{ m.TheValue } ");Console.WriteLine("");}static void Main(){var myInt = new [] { 20, 4, 16, 9, 2 };// Create array of MyClass objs.MyClass[] mcArr = new MyClass[5];// Initialize the array.for (int i = 0; i < 5; i++)           {mcArr[i] = new MyClass();mcArr[i].TheValue = myInt[i];}PrintOut("Initial Order:  ", mcArr);  // Print the initial array.// Sort the array.Array.Sort(mcArr);                    PrintOut("Sorted Order:   ", mcArr);  // Print the sorted array.}
}// output
Initial Order:  20 4 16 9 2
Sorted Order:   2 4 9 16 20

16.2 声明接口

接口声明不能包含以下成员:

  • 数据成员。

  • 静态成员。

接口声明只能包含如下类型的非静态成员:

  • 方法。

  • 属性。

  • 事件。

  • 索引器。

函数声明不能包含任何实现代码,使用分号代替函数主体。
接口名称必须从大写的 I 开始。
可以声明分部接口。

interface IMyInterface1
{   //Semicolon in place of bodyint    DoStuff ( int nVar1, long lVar2 );double DoOtherStuff( string s, long x );
}  

接口和接口成员的访问性有一些不同:
接口声明可以有任何的访问修饰符。
接口成员是隐式 public,不能有任何访问修饰符。

// 访问修饰符 可以用:public、protected、private、internal
public interface IMyInterface2
{// 错误private int Method1( int nVar1, long lVar2 );          
} 

16.3 实现接口

要实现接口,类和结构必须:

  1. 在基类列表中包含接口名称。
  2. 为每一个接口成员提供实现。
class MyClass: IMyInterface1
{int    DoStuff     ( int nVar1, long lVar2 ){ // ... }                                       double DoOtherStuff( string s, long x ){ // ... }                                     
}

重要事项如下:

  1. 必须实现接口的所有成员。
  2. 基类名称必须放在所有接口之前。
// 基类名、接口名
class Derived : MyBaseClass, IIfc1, IEnumerable, IComparable
{...
}

简单接口的示例

// Declare interface.
interface IIfc1   
{                        // Semicolon in place of bodyvoid PrintOut(string s);
}//Implement interface
class MyClass : IIfc1 // Declare class.
{public void PrintOut(string s)                  // Implementation{Console.WriteLine($"Calling through:  {s }");}
}class Program
{static void Main(){MyClass mc = new MyClass();                  // Create instance.mc.PrintOut("object");                       // Call method.}
}

16.4 接口是引用类型

接口是引用类型

不能通过类对象的成员访问接口,只能通过将类对象引用强制转换为接口类型来获取接口引用。

有了接口引用,可以使用点语法来调用接口的成员。

注意:接口引用不能调用类中不属于接口的其他成员。

interface IIfc1
{void PrintOut(string s);
}class MyClass : IIfc1
{public void PrintOut(string s){Console.WriteLine($"Calling through:  { s }");}
}class Program
{static void Main(){MyClass mc = new MyClass();  // Create class object.// Call class object implementation method.mc.PrintOut("object");       // Cast class object ref to interface ref.        IIfc1 ifc = (IIfc1)mc;       ifc.PrintOut("interface");   // Call interface method.}
}// outputCalling through:  objectCalling through:  interface

16.5 接口和 as 运算符

将类对象引用强制转换为类未实现的接口引用,则会抛出异常。

使用 as 运算符可以避免抛出异常:

  • 如果实现了类接口,则 as 返回指向接口的引用。
  • 如果未实现接口,则 as 返回 null,而不抛出异常。
// Acts like cast: (ILiveBirth)a
ILiveBirth b = a as ILiveBirth;        if (b != null)Console.WriteLine($"Baby is called: {b.BabyCalled() }");

16.6 实现多个接口

  1. 类或结构可以实现任意数量的接口
  2. 所有实现的接口必须列在基类列表中,以逗号分隔(在基类名称之后,如果有的话)。
// Declare interface.
interface IDataRetrieve { int GetData(); }           // Declare interface.
interface IDataStore    { void SetData( int x ); }// Interface Interface
class MyData: IDataRetrieve, IDataStore              
{int Mem1;                                         public int  GetData()        { return Mem1; }public void SetData( int x ) { Mem1 = x; }   
}class Program
{static void Main()                         {MyData data = new MyData();data.SetData( 5 );Console.WriteLine($"Value = {data.GetData() }");}
}// output
Value = 5

16.7 实现具有重复成员的接口

由于类可以实现任意数量的接口,有可能两个或多个接口成员具有相同的签名和返回类型,

如果一个类实现了多个接口,并且其中一些接口具有相同的成员,则类可以实现单个成员来同时匹配所有重复成员的接口。

类中用一个成员来匹配多个接口中的重复成员

interface IIfc1
{void PrintOut(string s);
}
interface IIfc2
{void PrintOut(string t);
}// Implement both interfaces.
class MyClass : IIfc1, IIfc2             
{// Single implementation for bothpublic void PrintOut(string s)        {Console.WriteLine($"Calling through:  { s }");}
}class Program
{static void Main(){MyClass mc = new MyClass();mc.PrintOut("object");}
}// outputCalling through:  object

16.8 多个接口的引用

如果类实现了多个接口,可以获取每个接口的独立引用

interface IIfc1
{void PrintOut(string s);
}
interface IIfc2
{void PrintOut(string t);
}// Implement both interfaces.
class MyClass : IIfc1, IIfc2             
{// Single implementation for bothpublic void PrintOut(string s)        {Console.WriteLine($"Calling through:  { s }");}
}class Program
{static void Main(){MyClass mc = new MyClass();// 获取接口的引用IIfc1 ifc1 = (IIfc1) mc;                 IIfc2 ifc2 = (IIfc2) mc;                 // 从类对象调用mc.PrintOut("object");     // 从接口调用ifc1.PrintOut("interface 1");           ifc2.PrintOut("interface 2");           }
}// outputCalling through:  objectCalling through:  interface 1Calling through:  interface 2

16.9 派生成员作为实现

实现接口的类可以从基类继承实现的代码。

interface IIfc1 { void PrintOut(string s); }class MyBaseClass                                   
{public void PrintOut(string s)                   {Console.WriteLine($"Calling through:  { s }");}}class Derived : MyBaseClass, IIfc1                 
{
}class Program {static void Main(){Derived d = new Derived();                    d.PrintOut("object.");                        }
}

16.10 显示接口成员实现

可以创建显示接口成员以实现相同接口的分离,

显示接口成员实现,主要特性:

位于实现了接口的类或结构中,

使用限定接口名称声明,由接口名称、成员函数、点分隔符组成

限定接口名称的声明如下:

// 声明接口
interface IIfc1 { void PrintOut(string s); } 
interface IIfc2 { void PrintOut(string t); }class MyClass : IIfc1, IIfc2
{// 限定接口名称void IIfc1.PrintOut(string s)            {  Console.WriteLine($"IIfc1:  {s }");}// Qualified interface namevoid IIfc2.PrintOut(string s)            {      Console.WriteLine($"IIfc2:  {s }");}
}class Program
{static void Main(){MyClass mc = new MyClass();IIfc1 ifc1 = (IIfc1) mc;              ifc1.PrintOut("interface 1");IIfc2 ifc2 = (IIfc2) mc;              ifc2.PrintOut("interface 2");         }
}// output
IIfc1:  interface 1
IIfc2:  interface 2

如果有显式接口成员实现,类级别实现是允许的,不是必须的,

因此,对于成员函数而言,有如下三种实现方法:

1.类级别实现(不依赖接口,专门提供给类对象调用)。
2.显示接口成员实现(依赖接口,专门提供给接口调用)。
3.类级别和显示接口成员实现(类和接口都能调用)。

显示接口成员实现只能通过接口来访问:

class MyClass : IIfc1
{// 显式接口实现void IIfc1.PrintOut(string s)      {Console.WriteLine("IIfc1");}public void Method1(){// 编译错误PrintOut("...");  // 编译错误this.PrintOut("...");// 转换为接口引用((IIfc1)this).PrintOut("...");  // OK, call method.}     
} 

16.11 接口可以继承接口

类在基类列表中只能有一个类名;而接口可以有任意多个接口。

interface IDataI0 : IDataRetrieve, IDataStore
{// ...
}
  • 列表中的接口本身也可以继承其他接口。
  • 继承后的接口包含自己的成员和所有继承接口的成员。
using System;// 定义数据检索接口
interface IDataRetrieve {int GetData();
}// 定义数据存储接口
interface IDataStore {void SetData(int value);
}// 组合接口
interface IDataIO : IDataRetrieve, IDataStore {}// 具体实现类
class MyData : IDataIO {private int nPrivateData;public int GetData() {return nPrivateData;}public void SetData(int value) {nPrivateData = value;}
}class Program {static void Main(string[] args) {MyData data = new MyData();data.SetData(5);Console.WriteLine("当前数据:{0}" + data.GetData());}
}

16.12 不同类实现一个接口的示例

interface ILiveBirth                           
{string BabyCalled();
}class Animal { }     class Cat : Animal, ILiveBirth                 
{string ILiveBirth.BabyCalled(){ return "kitten"; }
}class Dog : Animal, ILiveBirth                 
{string ILiveBirth.BabyCalled(){ return "puppy"; }
}class Bird : Animal                            
{
}class Program
{static void Main(){Animal[] animalArray = new Animal[3];   // Create Animal array.animalArray[0] = new Cat();             // Insert Cat class object.// Insert Bird class object.animalArray[1] = new Bird();            // Insert Dog class object.animalArray[2] = new Dog();  // Cycle through array.foreach( Animal a in animalArray )      {ILiveBirth b = a as ILiveBirth;      // if implements ILiveBirth...if (b != null)Console.WriteLine($"Baby is called: { b.BabyCalled() }");}}
}// output 
Baby is called: kitten
Baby is called: puppy

相关文章:

  • TCP流量控制与拥塞控制:核心机制与区别
  • Java 21 的虚拟线程与桥接模式:构建高性能并发系统
  • 【Dicom标准】dicom数据中pixelData显示处理流程详细介绍
  • Flink作业三种部署模式:架构、配置与实战应用
  • 由浅入深详解前缀树-Trie树
  • OC—多界面传值
  • Python 深度学习基础:TensorFlow 入门——从张量到神经网络的实战指南
  • Python 爬虫简单示例
  • 关于存储与网络基础的详细讲解(从属GESP二级内容)
  • React 核心原理与Fiber架构
  • [XILINX]ZYNQ7010_7020_软件LVDS设计
  • Spring Boot 项目初始化
  • HCIP-Datacom Core Technology V1.0_4 OSPF路由计算
  • 抽象工厂设计模式
  • 从C++编程入手设计模式——责任链模式
  • 大模型应用:如何使用Langchain+Qwen部署一套Rag检索系统
  • 【机器学习四大核心任务类型详解】分类、回归、聚类、降维都是什么?
  • OpenGL ES 中的材质
  • 分布式ID生成方式及优缺点详解
  • [特殊字符] AIGC工具深度实战:GPT与通义灵码如何彻底重构企业开发流程
  • 英文购物网站建设/网络推广的优势有哪些
  • 企业安全文化建设方案/吉安seo
  • 南宁网站建设教学/搜索引擎推广的基本方法有
  • 建站语言有哪些/外贸建站推广哪家好
  • 电商网站建设存在的问题和处理方案/东莞百度网站排名优化
  • 网站套模板教程/如何利用互联网进行宣传推广