多个接口
本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 27 课,共 70 课。
类只能继承一个基类,但可以根据需要实现任意多个接口。这是接口相较于抽象类的一大优势:它们允许类采用多种行为。
要实现多个接口,只需在冒号后用逗号分隔列出它们:
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}Duck 类必须实现两个接口中的所有成员。这自然地模拟了现实世界的场景:鸭子确实既会飞也会游泳,因此让它满足这两个契约是合理的。
将继承与多个接口结合使用时,基类必须放在最前面:
public class Duck : Bird, IFlyable, ISwimmable
{
// 继承 Bird 类,并实现两个接口
}这种灵活性让你可以组合来自多个来源的行为。一个 Robot 可能会实现 IMovable、IChargeable 和 ISpeakable。每个接口代表一种能力,你的类可以根据需要自由组合。
挑战
简单让我们构建一个智能家居设备系统,展示一个类如何实现多个接口,从而获得不同的功能。你将创建既可控制又具有电源管理功能的设备。
你将把代码分散到 4 个文件中:
IControllable.cs:在SmartHome命名空间中定义一个名为IControllable的接口。这个接口表示可以开启和关闭的设备。它应声明两个方法:TurnOn()和TurnOff(),两者都返回一个字符串。INetworkConnected.cs:在SmartHome命名空间中定义一个名为INetworkConnected的接口。这个接口表示可以连接到网络的设备。它应声明一个方法Connect(string network),该方法返回一个字符串。SmartTV.cs:在SmartHome命名空间中定义一个SmartTV类,同时实现IControllable和INetworkConnected。电视应有一个Brand属性(字符串)和一个ScreenSize属性(int,表示英寸)。创建一个接受这两个值的构造函数。实现所有接口方法:TurnOn()返回"{Brand} {ScreenSize}-inch TV is now ON"TurnOff()返回"{Brand} {ScreenSize}-inch TV is now OFF"Connect(string network)返回"{Brand} TV connected to {network}"
Program.cs:在主文件中,使用输入值创建一个SmartTV。通过将同一个电视对象存储为三种不同的变量类型,展示多个接口带来的灵活性:具体的SmartTV类型、一个IControllable变量,以及一个INetworkConnected变量。通过每个引用调用相应的方法,展示同一个对象如何根据你使用的接口而以不同方式使用。
你将收到 3 个输入:
- 电视品牌名称
- 屏幕尺寸,单位为英寸
- 要连接的网络名称
按以下格式输出:
Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}例如,如果输入为 Samsung、55 和 HomeWiFi,输出应为:
Via SmartTV:
Samsung 55-inch TV is now ON
Samsung TV connected to HomeWiFi
Via IControllable:
Samsung 55-inch TV is now OFF
Via INetworkConnected:
Samsung TV connected to HomeWiFi注意,同一个 SmartTV 对象可以通过不同的接口引用进行访问。当它存储为 IControllable 时,你只能调用控制方法。当它存储为 INetworkConnected 时,你只能调用网络方法。这就是实现多个接口的优势:一个类可以获得多种功能,同时在使用方式上保持灵活!
亲手试试
using System;
using SmartHome;
class Program
{
public static void Main(string[] args)
{
// 读取输入
string brand = Console.ReadLine();
int screenSize = Convert.ToInt32(Console.ReadLine());
string network = Console.ReadLine();
// TODO: 用输入值创建一个 SmartTV 对象
// TODO: 用 3 种不同类型的变量存储同一个 TV 对象:
// 1. SmartTV 类型(具体类)
// 2. IControllable 类型(接口引用)
// 3. INetworkConnected 类型(接口引用)
// TODO: 按要求的格式打印输出:
// Via SmartTV:
// 调用 TurnOn() 和 Connect(network)
// Via IControllable:
// 调用 TurnOff()
// Via INetworkConnected:
// 调用 Connect(network)
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C# 在线编译器