面向对象进阶 - 接口

3 阅读6分钟

专栏导航

一、什么是接口?

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 抽象类的区别
  • ✅ 实践了完整的智能家居系统