专栏导航
- ← 上一篇:面向对象进阶 - 抽象类
- ← 第一篇:编程世界初探
- 专栏目录
一、什么是接口?
1.1 现实生活中的接口
想象一下:
"遥控器"是一个接口
└── 控制电视(实现接口)
└── 控制空调(实现接口)
└── 控制音响(实现接口)
遥控器定义了一套按钮(开、关、音量等),不同设备都可以通过实现这个接口来被控制。
1.2 编程中的接口
接口(Interface)是一种定义"契约"的类型。它只定义方法、属性等的签名,不提供具体实现。类通过实现接口来承诺提供这些功能。
接口(IPlayable)
├── 音乐播放器(实现接口)
├── 视频播放器(实现接口)
└── 游戏机(实现接口)
1.3 为什么要使用接口?
好处:
✅ 契约定义:明确类必须实现的功能
✅ 多重继承:一个类可以实现多个接口
✅ 松耦合:降低代码之间的依赖
✅ 多态支持:统一处理不同类型的对象
✅ 灵活设计:易于扩展和维护
二、interface 关键字
2.1 基本语法
// 定义接口(使用 interface 关键字,接口名通常以 I 开头)
interface 接口名
{
// 方法签名(没有实现)
返回类型 方法名(参数);
// 属性签名
类型 属性名 { get; set; }
}
// 实现接口
class 类名 : 接口名
{
// 必须实现接口的所有成员
public 返回类型 方法名(参数)
{
// 实现代码
}
}
2.2 接口的特点
| 特点 | 说明 |
|---|---|
| 不能实例化 | new IPlayable() 是错误的 |
| 不能包含实现 | 只有方法签名 |
| 成员默认 public | 不需要写访问修饰符 |
| 可以多重继承 | 一个类可以实现多个接口 |
| 成员自动是 abstract | 不需要写 abstract 关键字 |
三、简单接口示例
3.1 基本示例:可播放接口
using System;
namespace Week11Practice
{
// 接口:可播放
interface IPlayable
{
void Play();
void Pause();
void Stop();
}
// 实现接口:音乐播放器
class MusicPlayer : IPlayable
{
private string currentSong;
public MusicPlayer(string song)
{
currentSong = song;
}
public void Play()
{
Console.WriteLine($"🎵 播放音乐: {currentSong}");
}
public void Pause()
{
Console.WriteLine($"⏸️ 暂停音乐: {currentSong}");
}
public void Stop()
{
Console.WriteLine($"⏹️ 停止音乐: {currentSong}");
}
}
// 实现接口:视频播放器
class VideoPlayer : IPlayable
{
private string currentVideo;
public VideoPlayer(string video)
{
currentVideo = video;
}
public void Play()
{
Console.WriteLine($"🎬 播放视频: {currentVideo}");
}
public void Pause()
{
Console.WriteLine($"⏸️ 暂停视频: {currentVideo}");
}
public void Stop()
{
Console.WriteLine($"⏹️ 停止视频: {currentVideo}");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 接口示例:播放器 =====\n");
List<IPlayable> players = new List<IPlayable>
{
new MusicPlayer("青花瓷"),
new VideoPlayer("复仇者联盟"),
new MusicPlayer("告白气球")
};
foreach (IPlayable player in players)
{
player.Play();
player.Pause();
player.Stop();
Console.WriteLine();
}
// ❌ 不能实例化接口
// IPlayable player = new IPlayable(); // 编译错误
}
}
}
输出:
===== 接口示例:播放器 =====
🎵 播放音乐: 青花瓷
⏸️ 暂停音乐: 青花瓷
⏹️ 停止音乐: 青花瓷
🎬 播放视频: 复仇者联盟
⏸️ 暂停视频: 复仇者联盟
⏹️ 停止视频: 复仇者联盟
🎵 播放音乐: 告白气球
⏸️ 暂停音乐: 告白气球
⏹️ 停止音乐: 告白气球
3.2 接口命名规范
接口名称通常以 I 开头,表示它是一个接口。
// ✅ 推荐:以 I 开头
interface IPlayable { }
interface IAnimal { }
interface IShape { }
interface IEmployee { }
// ❌ 不推荐:不以 I 开头
interface Playable { }
interface Animal { }
interface Shape { }
四、接口中的成员
4.1 接口可以包含的成员
| 成员类型 | 说明 |
|---|---|
| 方法 | 只有签名,没有实现 |
| 属性 | 只有 get/set |
| 索引器 | 类似属性 |
| 事件 | 事件声明 |
| 默认方法(C# 8.0+) | 可以有默认实现 |
4.2 接口成员示例
interface IShape
{
// 方法
double CalculateArea();
double CalculatePerimeter();
// 属性
string Name { get; }
int Sides { get; }
// 索引器
double this[int index] { get; }
}
五、实现多个接口
5.1 多接口实现
一个类可以实现多个接口,用逗号分隔。
using System;
namespace Week11Practice
{
// 接口1:可飞
interface IFlyable
{
void Fly();
void TakeOff();
void Land();
}
// 接口2:可游泳
interface ISwimmable
{
void Swim();
void Dive();
}
// 接口3:可跑
interface IRunnable
{
void Run();
void Jump();
}
// 实现多个接口的类:鸭子
class Duck : IFlyable, ISwimmable, IRunnable
{
public void Fly()
{
Console.WriteLine("🦆 鸭子在飞...");
}
public void TakeOff()
{
Console.WriteLine("🦆 鸭子起飞!");
}
public void Land()
{
Console.WriteLine("🦆 鸭子降落!");
}
public void Swim()
{
Console.WriteLine("🦆 鸭子在游泳...");
}
public void Dive()
{
Console.WriteLine("🦆 鸭子潜水!");
}
public void Run()
{
Console.WriteLine("🦆 鸭子在跑...");
}
public void Jump()
{
Console.WriteLine("🦆 鸭子跳!");
}
}
// 实现部分接口的类:飞机
class Airplane : IFlyable
{
public void Fly()
{
Console.WriteLine("✈️ 飞机在飞行...");
}
public void TakeOff()
{
Console.WriteLine("✈️ 飞机起飞!");
}
public void Land()
{
Console.WriteLine("✈️ 飞机降落!");
}
}
// 实现部分接口的类:鱼
class Fish : ISwimmable
{
public void Swim()
{
Console.WriteLine("🐟 鱼在游泳...");
}
public void Dive()
{
Console.WriteLine("🐟 鱼潜水!");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 多接口示例 =====\n");
// 鸭子:会飞、会游泳、会跑
Duck duck = new Duck();
Console.WriteLine("--- 鸭子 ---");
duck.Fly();
duck.Swim();
duck.Run();
Console.WriteLine();
// 飞机:只会飞
Airplane airplane = new Airplane();
Console.WriteLine("--- 飞机 ---");
airplane.Fly();
Console.WriteLine();
// 鱼:只会游泳
Fish fish = new Fish();
Console.WriteLine("--- 鱼 ---");
fish.Swim();
// 使用接口类型
Console.WriteLine("\n--- 使用接口类型 ---");
IFlyable[] flyingObjects = { new Duck(), new Airplane() };
foreach (IFlyable flyer in flyingObjects)
{
flyer.Fly();
}
}
}
}
输出:
===== 多接口示例 =====
--- 鸭子 ---
🦆 鸭子在飞...
🦆 鸭子在游泳...
🦆 鸭子在跑...
--- 飞机 ---
✈️ 飞机在飞行...
--- 鱼 ---
🐟 鱼在游泳...
--- 使用接口类型 ---
🦆 鸭子在飞...
✈️ 飞机在飞行...
六、接口 vs 抽象类
6.1 对比表格
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 实现方式 | class 子类 : 父类 | class 类 : 接口 |
| 继承数量 | 单继承 | 多继承 |
| 成员实现 | 可以有部分实现 | 不能有实现(C# 8.0+ 除外) |
| 访问修饰符 | 可以使用各种修饰符 | 默认 public |
| 字段 | 可以有字段 | 不能有字段 |
| 构造函数 | 可以有构造函数 | 不能有构造函数 |
| 使用场景 | IS-A 关系(是一个) | CAN-DO 关系(能够做) |
| 代码复用 | 适合 | 不适合 |
6.2 如何选择?
使用抽象类当:
- 需要提供部分实现
- 需要共享代码
- 建立 IS-A 关系(狗是动物)
使用接口当:
- 需要定义契约/规范
- 需要多重继承
- 建立 CAN-DO 关系(狗能够跑)
6.3 示例对比
// 抽象类:适合 IS-A 关系
abstract class Animal
{
public string Name { get; set; }
// 提供通用实现
public void Sleep()
{
Console.WriteLine($"{Name} 睡觉...");
}
// 要求派生类实现
public abstract void MakeSound();
}
// 接口:适合 CAN-DO 关系
interface IFlyable
{
void Fly();
}
interface ISwimmable
{
void Swim();
}
// 组合使用
class Bird : Animal, IFlyable
{
public Bird(string name)
{
Name = name;
}
public override void MakeSound()
{
Console.WriteLine("叽叽喳喳");
}
public void Fly()
{
Console.WriteLine($"{Name} 在飞...");
}
}
class Duck : Animal, IFlyable, ISwimmable
{
public Duck(string name)
{
Name = name;
}
public override void MakeSound()
{
Console.WriteLine("嘎嘎嘎");
}
public void Fly()
{
Console.WriteLine($"{Name} 在飞...");
}
public void Swim()
{
Console.WriteLine($"{Name} 在游泳...");
}
}
七、实践示例:智能家居系统
using System;
using System.Collections.Generic;
namespace Week11Practice
{
// 接口:可控制
interface IControllable
{
void TurnOn();
void TurnOff();
string GetStatus();
}
// 接口:可调温
interface IAdjustableTemperature
{
void SetTemperature(int temp);
int GetCurrentTemperature();
}
// 接口:可调亮度
interface IAdjustableBrightness
{
void SetBrightness(int level);
int GetBrightness();
}
// 智能灯泡
class SmartLight : IControllable, IAdjustableBrightness
{
public bool IsOn { get; private set; }
public int Brightness { get; private set; }
public SmartLight()
{
Brightness = 100;
}
public void TurnOn()
{
IsOn = true;
Console.WriteLine("💡 灯泡已开启");
}
public void TurnOff()
{
IsOn = false;
Console.WriteLine("💡 灯泡已关闭");
}
public string GetStatus()
{
return $"灯泡: {(IsOn ? "开启" : "关闭")}, 亮度: {Brightness}%";
}
public void SetBrightness(int level)
{
if (level >= 0 && level <= 100)
{
Brightness = level;
Console.WriteLine($"💡 亮度设置为: {Brightness}%");
}
else
{
Console.WriteLine("亮度必须在 0-100 之间!");
}
}
public int GetBrightness()
{
return Brightness;
}
}
// 智能空调
class SmartAirConditioner : IControllable, IAdjustableTemperature
{
public bool IsOn { get; private set; }
public int Temperature { get; private set; }
public SmartAirConditioner()
{
Temperature = 26;
}
public void TurnOn()
{
IsOn = true;
Console.WriteLine("❄️ 空调已开启");
}
public void TurnOff()
{
IsOn = false;
Console.WriteLine("❄️ 空调已关闭");
}
public string GetStatus()
{
return $"空调: {(IsOn ? "开启" : "关闭")}, 温度: {Temperature}°C";
}
public void SetTemperature(int temp)
{
if (temp >= 16 && temp <= 30)
{
Temperature = temp;
Console.WriteLine($"❄️ 温度设置为: {Temperature}°C");
}
else
{
Console.WriteLine("温度必须在 16-30°C 之间!");
}
}
public int GetCurrentTemperature()
{
return Temperature;
}
}
// 智能窗帘
class SmartCurtain : IControllable
{
public bool IsOpen { get; private set; }
public void TurnOn()
{
IsOpen = true;
Console.WriteLine("🪟 窗帘已打开");
}
public void TurnOff()
{
IsOpen = false;
Console.WriteLine("🪟 窗帘已关闭");
}
public string GetStatus()
{
return $"窗帘: {(IsOpen ? "打开" : "关闭")}";
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 智能家居系统 =====\n");
List<IControllable> devices = new List<IControllable>
{
new SmartLight(),
new SmartAirConditioner(),
new SmartCurtain()
};
// 控制所有设备
Console.WriteLine("--- 开启所有设备 ---");
foreach (var device in devices)
{
device.TurnOn();
}
Console.WriteLine();
// 显示所有设备状态
Console.WriteLine("--- 设备状态 ---");
foreach (var device in devices)
{
Console.WriteLine(device.GetStatus());
}
Console.WriteLine();
// 测试特定接口功能
Console.WriteLine("--- 测试可调温设备 ---");
SmartAirConditioner ac = new SmartAirConditioner();
ac.TurnOn();
ac.SetTemperature(24);
Console.WriteLine(ac.GetStatus());
Console.WriteLine();
Console.WriteLine("--- 测试可调亮度设备 ---");
SmartLight light = new SmartLight();
light.TurnOn();
light.SetBrightness(50);
Console.WriteLine(light.GetStatus());
}
}
}
输出:
===== 智能家居系统 =====
--- 开启所有设备 ---
💡 灯泡已开启
❄️ 空调已开启
🪟 窗帘已打开
--- 设备状态 ---
灯泡: 开启, 亮度: 100%
空调: 开启, 温度: 26°C
窗帘: 打开
--- 测试可调温设备 ---
❄️ 空调已开启
❄️ 温度设置为: 24°C
空调: 开启, 温度: 24°C
--- 测试可调亮度设备 ---
💡 灯泡已开启
💡 亮度设置为: 50%
灯泡: 开启, 亮度: 50%
八、接口的多态
8.1 使用接口实现多态
interface IPaymentMethod
{
string Name { get; }
bool Pay(decimal amount);
}
class CreditCard : IPaymentMethod
{
public string Name => "信用卡";
public bool Pay(decimal amount)
{
Console.WriteLine($"使用{Name}支付 {amount:C}");
return true;
}
}
class Alipay : IPaymentMethod
{
public string Name => "支付宝";
public bool Pay(decimal amount)
{
Console.WriteLine($"使用{Name}支付 {amount:C}");
return true;
}
}
class Program
{
static void ProcessPayment(IPaymentMethod payment, decimal amount)
{
Console.WriteLine($"处理支付:{payment.Name}");
payment.Pay(amount);
}
static void Main()
{
List<IPaymentMethod> payments = new List<IPaymentMethod>
{
new CreditCard(),
new Alipay()
};
foreach (var payment in payments)
{
ProcessPayment(payment, 100);
}
}
}
本章总结
- ✅ 理解了接口的概念和作用
- ✅ 学会了使用 interface 关键字
- ✅ 掌握了接口的实现方法
- ✅ 理解了多接口实现
- ✅ 掌握了接口 vs 抽象类的区别
- ✅ 实践了完整的智能家居系统