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

C# 接口(什么是接口)

什么是接口

接口是指定一组函数成员而不实现它们的引用类型。所以只能类和结构来实现接囗。这种描
述听起来有点抽象,因此先来看看接口能够帮助我们解决的问题,以及是如何解决的。

以下面的代码为例。观察program类中的Main方法,它创建并初始化了一个CA类的对象,
并将该对象传递给PrintInfo方法。PrintInfo需要一个CA类型的对象,并打印包含在该对象
内的信息。

class CA
{public string Name;public int Age;
}class CB
{public string First;public string Last;public double PersonsAge;
}class Program
{static void PrintInfo(CA item){Console.WriteLine($"Name:{item.Name},Age:{item.Age}");}static void Main(){CA a=new CA() {Name="John Doe",Age=35};PrintInfo(a);}
}

只要传入的是CA类型的对象,PrintInfo方法就能工作正常。但如果传入的是CB类型的对
象(同样见上面的代码),就不行了。假设PrintInfo方法中的算法非常有用,我们想用它操
作不同类的对象。

现在的代码不能满足上面的需求,原因有很多。首先,PrintInfo的形参指明了实参必须为
CA类型的对象,因此传人CB或其他类型的对象将导致编译错误。但即使能克服这个障碍,使其
接受CB类型的对象还是会有问题,因为CB的结构与CA的不同。其字段的名称和类型与不一
样,PrintInfo对这些字段一无所知。

能不能创建一个能够成功传人PrintInfo的类,并且不管该类是什么样的结构,PrintInfo
都能正常处理呢?接口使这种设想变为可能。
图16-1中的代码使用接口解决了这一问题。你现在不需要理解细节,但一般来说,注意以下几点。

  • 首先,它声明了一个llnfo接口,其中包含两个方法一GetName和GetAge,每个方法
    都返回string。
  • 类CA和CB各自实现了llnfo接口(将其放到基类列表中),并实现了该接口所需的两个
  • Main创建了CA和的实例,并传人PrintInfo。
  • 由于类实例实现了接口,PrintInfo可以调用那两个方法,每个类实例执行各自的方法,
    就好像是执行自己类声明中的方法。
interface IInfo       //声明接口
{string GetName();string GetAge();
}class CA:IInfo  //声明实现接口的CA类
{public string Name;public int Age;public string GetName(){return Name;}  //在CA类中实现两个接口方法public string GetAge(){return Age.ToString();}
}class CB:IInfo  //声明实现接口的CB类
{public string First;public string Last;public double PersonsAge;public string GetName(){return First+","+Last;}  //在CB类中实现两个接口方法public string GetAge(){return PersonsAge.ToString();}
}class Program
{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",PersonsAge=33};PrintInfo(a);    PrintInfo(b);         //对象的引用能自动转换为他们的接口的引用}
}

使用IComparable接口的示例
我们已经了解了接口能够解决的问题,接下来看第二个示例并深入一些细节。先来看看如下
代码,它接受了一个没有排序的整数数组并且按升序进行排序。这段代码的功能如下:

  • 第一行代码创建了包含5个无序整数的数组;
  • 第二行代码使用了Array类的静态sort方法来对元素排序;
  • 用foreach循环输出它们,显示以升序排序的数字。

Array类的sort方法在int数组上工作得很好,但是如果我们尝试在自己的类数组上使用会
发生什么呢?如下所示:

class MyClass  //声明一个简单类
{public int TheValue;
}...
MyClass[] mc=new MyClass[5]; //创建一个有5个元素的数组//创建并初始化元素Array.Sort(mc);              //尝试使用Sort时抛出异常

如果你尝试运行这段代码的话,不会进行排序而是会得到一个异常。sort不能针对Myclass
对象数组进行排序的原因是,它不知道如何比较用户定义的对象以及如何进行排序。Array类的
sort方法其实依赖于一个叫作1Comparable的接口,它声明在BCL中,包含唯一的方法CompareTo。

下面的代码展示了IComparable接口的声明。注意,接口主体内包含CompareTo方法的声明,
指定了它接受一个object类型的参数。尽管该方法具有名称、参数和返回类型,却没有实现。
它的实现用一个分号表示。

image
图16-2演示了IComparable接口。CompareTo方法用灰色框显示,以表明它不包含实现。

展示IComparable接口

尽管在接口声明中没有为CompareTo方法提供实现,但IComparable接口的.NET文档中描述
了该方法应该做的事情,你可以在创建实现该接口的类或结构时参考。文档中写道,在调用
方法时,它应该返回以下几个值之一

  • 负数值如果当前对象小于参数对象;
  • 正数值如果当前对象大于参数对象;、
  • 零如果两个对象在比较时相等。

Sort使用的算法依赖于使用元素的CompareTo方法来决定两个元素的次序。int类型实现了
lcomparable,但是myClass没有,因此当Sort尝试调用MyClass不存在的CompareTo方法时会
抛出异常。

我们可以通过让类实现IComparable,让Sort方法可以用于MyClass类型的对象。要实现一
个接口,类或结构必须做两件事情:

  • 在基类列表中列出接口名称;
  • 为接口的每一个成员提供实现。
    例如,下面的代码更新了MyClass来实现IComparab1e接口。注意下面关于代码的内容。
  • 接口名称列在类声明的基类列表中。
  • 类实现了一个名为compareTo的方法,它的参数类型和返回类型与接口成员一致。
  • 实现CompareTo方法以遵循接口文档的定义。也就是说,它将它的值与传人方法的对象值
    进行比较,并据此返回一1、1或0。
class MyClass:IComparable  //基类列表中的接口名称
{public int ThValue;public int CompareTo(Object obj)  //接口方法的实现{MyClass mc=(MyClass)obj;if(this.ThValue<mc.ThValue) return -1;if(this.ThValue>mc.TheValue) return -1;return 0;}
}

图16-3演示了更新后的类。从有阴影的接口方法指向类方法的箭头表示接口方法不包含代
码,而是在类级别的方法中实现。

在MyClass中实现IComparal

下面显示了更新后的完整代码,现在可以使用sort方法来排序MyClass对象数组了。Main
创建并初始化了MyClass对象的数组并且输出它们,然后调用了sort并重新输出,以显示它们
已经排好序了。

class MyClass:IComparable   //类实现接口
{public int TheValue; public int CompareTo(object obj)  //实现方法{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};MyClass[] mcArr=new MyClass[5];    //创建Myclass对象for(int i=0;i<5;i++){mcArr[i]=new MyClass();mcArr[i].TheValue=myInt[i];}PrintOut("Initial Order:",mcArr);//输出初始数组Array.Sort(mcArr);               //数组排序PrintOut("Sorted Order:   ",mcArr);//输出排序后的数组
}
http://www.lryc.cn/news/581740.html

相关文章:

  • 【机器学习笔记Ⅰ】1 机器学习
  • .golangci.yml文件配置
  • C语言学习(第一天)
  • 求医十年,病因不明,ChatGPT:你看起来有基因突变
  • Gin 框架中如何实现 JWT 鉴权中间件
  • PH热榜 | 2025-07-06
  • 宏定义实现自定义关系运算比较--3
  • 微服务负载均衡全解析:从原理到实践
  • 【王树森推荐系统】召回05:矩阵补充、最近邻查找
  • 操作系统【2】【内存管理】【虚拟内存】【参考小林code】
  • Linux - Linux基础知识
  • 数据挖掘:深度解析与实战应用
  • AI+Web3:从自动化工具到自主经济体的范式革命
  • 电信、移动、联通、广电跨运营商网速慢原因
  • 基于文心开源大模型ERNIE-4.5-0.3B-Paddle私有化部署并构建一个企业智能客服系统
  • SpringBoot基于Mysql的商业辅助决策系统设计与实现
  • Python实现优雅的目录结构打印工具
  • 暑假算法日记第二天
  • 李宏毅genai笔记:LLM内部机制
  • ubuntu 安装 MQTT服务器 mosquitto homeassistant 并在HA中集成MQTT
  • Solidity——returns和return区别、命名式返回、解构式赋值
  • 【代码问题】【模型下载】从 HuggingFace 上下载模型
  • 2、Connecting to Kafka
  • 大模型关键字解释
  • 【机器学习笔记Ⅰ】4 梯度下降
  • 【管理学】乐嘉性格色彩与MBTI的优劣和适用场景
  • 【C++基础】内存管理四重奏:malloc/free vs new/delete - 面试高频考点与真题解析
  • 汇编与接口技术:8259中断实验
  • 高效处理大体积Excel文件的Java技术方案解析
  • 从0写自己的操作系统(4)实现简单的任务切换