C#——Interface(接口)

接口应用场景:

一、场景 1:定义契约(规范行为),实现 "约定优于配置"

这是接口最基础也最核心的作用:接口定义了一组 "必须实现的行为"(方法、属性、事件等),但不提供具体实现,相当于一份 "契约"。任何类实现这个接口,就必须遵守契约,实现接口中的所有成员。

适用场景

当你需要让多个不同的类都具备相同的行为,但每个类的实现方式不同时,用接口定义这份行为契约。

// 定义接口:契约是"具备打印功能"

public interface IPrintable

{

// 只定义方法签名,没有具体实现

void Print();

}

// 类1:文档类,实现"可打印"契约

public class Document : IPrintable

{

public string Content { get; set; }

// 实现接口的Print方法(文档的打印逻辑)

public void Print()

{

Console.WriteLine($"打印文档:{Content}");

}

}

// 类2:图片类,实现"可打印"契约

public class Image : IPrintable

{

public string ImagePath { get; set; }

// 实现接口的Print方法(图片的打印逻辑)

public void Print()

{

Console.WriteLine($"打印图片:{ImagePath}");

}

}

// 调用端:只依赖接口,不依赖具体类

public class PrintManager

{

// 方法参数是接口类型,接收任何实现了IPrintable的类

public void PrintItem(IPrintable printable)

{

printable.Print(); // 调用的是具体类的实现

}

}

// 测试代码

class Program

{

static void Main()

{

PrintManager manager = new PrintManager();

// 传入Document实例

manager.PrintItem(new Document { Content = "Hello World" });

// 传入Image实例

manager.PrintItem(new Image { ImagePath = "photo.jpg" });

}

}

二、场景 2:解决类的单继承限制,实现 "多继承式" 的行为复用

C# 中类只能单继承 (一个类只能有一个父类),但可以实现多个接口,这让类可以具备多个不同的行为维度,弥补了单继承的不足。

适用场景:

当一个类需要具备多种不同的行为(比如既可以打印,又可以序列化),而这些行为来自不同的 "维度" 时,用多个接口实现。

// 接口1:可打印

public interface IPrintable

{

void Print();

}

// 接口2:可序列化

public interface ISerializable

{

string Serialize();

}

// 类:同时实现两个接口,具备两种行为

public class User : IPrintable, ISerializable

{

public string Name { get; set; }

public int Age { get; set; }

// 实现IPrintable的Print方法

public void Print()

{

Console.WriteLine($"打印用户信息:{Name},{Age}岁");

}

// 实现ISerializable的Serialize方法

public string Serialize()

{

return $"{{\"Name\":\"{Name}\",\"Age\":{Age}}}";

}

}

// 测试代码

class Program

{

static void Main()

{

User user = new User { Name = "张三", Age = 20 };

user.Print(); // 调用打印行为

Console.WriteLine(user.Serialize()); // 调用序列化行为

}

}

三、场景 3:实现解耦,提升代码的可测试性和可维护性

在实际开发中(尤其是分层架构、依赖注入场景),接口是解耦的关键:上层代码依赖接口,下层代码实现接口,从而让上下层代码互不依赖具体实现,只依赖契约。

适用场景

  • 分层架构(如 UI 层依赖业务逻辑层的接口,而非具体的业务类)。
  • 依赖注入(DI)和控制反转(IOC):比如ASP.NET Core 中的服务注入。
  • 单元测试:用 mock 对象(如 Moq 框架)模拟接口的实现,测试上层代码。

// 第一步:定义业务接口(契约)

public interface IUserService

{

string GetUserName(int id);

}

// 第二步:实现接口(具体业务逻辑)

public class UserService : IUserService

{

// 模拟从数据库获取数据

public string GetUserName(int id)

{

return id == 1 ? "张三" : "未知用户";

}

}

// 第三步:上层代码(如UI层)依赖接口,不依赖具体实现

public class UserController

{

private readonly IUserService _userService;

// 构造函数注入接口实例

public UserController(IUserService userService)

{

_userService = userService;

}

public void ShowUserName(int id)

{

Console.WriteLine(_userService.GetUserName(id));

}

}

// 测试代码

class Program

{

static void Main()

{

// 1. 实际运行时:传入真实的UserService

IUserService realService = new UserService();

UserController controller = new UserController(realService);

controller.ShowUserName(1); // 输出:张三

// 2. 单元测试时:传入mock的IUserService(无需连接数据库)

// var mockService = new Mock<IUserService>();

// mockService.Setup(s => s.GetUserName(1)).Returns("测试用户");

// UserController testController = new UserController(mockService.Object);

// testController.ShowUserName(1); // 输出:测试用户

}

}

相关推荐
小糯米6011 分钟前
C语言文件操作
c语言·开发语言·数据结构
caimouse2 分钟前
Reactos 第 9 章 设备驱动 — 9.4 内核劳务线程
开发语言·windows
Doker 多克5 分钟前
Spring AI Alibaba—快速构建ReactAgent
java·开发语言·前端·ai编程
张忠琳12 分钟前
【Go 1.26.4】Golang Slice 深度解析
开发语言·后端·golang
码云骑士30 分钟前
09-Python模块导入机制-sys.path与循环导入的死锁式排查
开发语言·python
星恒随风31 分钟前
C++ 模板初阶:从泛型编程、函数模板到类模板,一篇打通基础概念
开发语言·c++·笔记·学习
郝学胜-神的一滴35 分钟前
Qt 高级开发 031:QListWidget图标布局实战
开发语言·c++·qt·程序人生·软件构建·用户界面
caimouse36 分钟前
Reactos 第 8 章 结构化异常处理 — 8.4 软异常
服务器·开发语言·windows
艾莉丝努力练剑37 分钟前
【Qt】界面优化:绘图API
linux·运维·开发语言·网络·qt·tcp/ip·udp
牛油果子哥q38 分钟前
队列(Queue)深度精讲,先进先出原理、顺序/链式/循环队列、STL queue底层、栈队列互模拟与面试考点全解
开发语言·c++·面试