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); // 输出:测试用户

}

}

相关推荐
利刃大大7 小时前
【JavaSE】十九、JVM运行流程 && 类加载Class Loading
java·开发语言·jvm
Henry_Wu0017 小时前
go与c# 及nats和rabbitmq交互
golang·c#·rabbitmq·grpc·nats
Clarence Liu7 小时前
Go Context 深度解析:从源码到 RESTful 框架的最佳实践
开发语言·后端·golang
中年程序员一枚7 小时前
Python防止重复资源的链接mysql方法
开发语言·python·mysql
果然途游7 小时前
完整Java后端学习路径
java·开发语言·学习笔记
l1t7 小时前
Javascript引擎node bun deno比较
开发语言·javascript·算法·ecmascript·bun·精确覆盖·teris
sang_xb7 小时前
Android 系统的权限管理最佳实践
android·开发语言
信看7 小时前
树莓派CAN(FD) 测试
开发语言·python
爱吃大芒果8 小时前
Flutter 列表优化:ListView 性能调优与复杂列表实现
开发语言·hive·hadoop·flutter·华为