目录

C# 接口 (Interface) 深度解析

接口(Interface)是 C# 面向对象编程中非常核心的概念。它定义了“行为的规范”,起到了强制契约的作用。

1. 接口简介

关键字:interface (读音: /'ɪntəfeɪs/)

接口定义了所有类继承接口时应遵循的语法合同。接口定义了“是什么”(规范),而不关心“怎么做”(实现)。

核心特性

记忆口诀:接口像是一个“职位描述(JD)”,类像是“员工”。JD 规定了员工必须会做什么(比如会编程、会英语),但具体怎么编程、怎么说英语,由员工(类)自己决定。

2. 基础语法与多态

为了实现多态(Polymorphism),我们通常使用接口类型的变量来引用子类的对象

class Program
{
    static void Main(string[] args)
    {
        // 多态的核心:左边是接口,右边是具体实现类
        // IAnimal myDog = new IAnimal(); // 错误!接口不能被实例化
 
        IAnimal myDog = new Dog(); 
 
        // 调用接口的方法,实际执行的是 Dog 类中具体的实现
        myDog.MakeSound(); // 输出 "Woof!"
    }
}
 
// 1. 定义接口 (通常以 I 开头命名)
interface IAnimal
{
    void MakeSound(); // 只有声明,没有方法体
}
 
// 2. 实现接口
class Dog : IAnimal
{
    // 必须实现接口中的所有方法,且必须是 public
    public void MakeSound()
    {
        Console.WriteLine("Woof! Im a Dog!");
    }
}

3. 接口成员:属性与方法

接口不仅可以定义方法,还可以定义属性。

注意:在你提供的示例中,`Main` 函数尝试给属性赋值,但接口定义中只有 `get`。为了让代码能运行,下面的示例修正了 `set` 访问器。

class Program
{
    static void Main(string[] args)
    {
        // 实例化实现类
        ClassGetInformation syong = new ClassGetInformation();
 
        // 使用属性
        syong.Name = "智能手机";
        syong.Code = "00254";
 
        // 调用方法
        syong.ShowInfo();
    }
}
 
// 定义接口
interface IInformation
{
    // 接口中的属性通常指明需要 get 还是 set
    string Code { get; set; } 
    string Name { get; set; } 
    void ShowInfo();
}
 
// 自定义类实现接口
public class ClassGetInformation : IInformation
{
    // 私有字段
    private string _code = "";
    private string _name = "";
 
    // 实现接口属性 Code
    public string Code 
    {
        get { return _code; }
        set { _code = value; }
    }
 
    // 实现接口属性 Name
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
 
    // 实现接口方法
    public void ShowInfo() 
    {
        Console.WriteLine($"设备名称: {Name}, 编号: {Code}");
    }
}

4. 接口的多态性 (进阶举例)

这是接口最常见的应用场景:统一管理不同的对象

using System;
 
class Program
{
    static void Main(string[] args)
    {
        // 使用接口数组或集合,可以同时管理 Dog 和 Cat
        IAnimal[] animals = new IAnimal[2];
 
        animals[0] = new Dog();
        animals[1] = new Cat();
 
        // 遍历集合,虽然都是 IAnimal 类型,但表现出不同的行为
        foreach (var animal in animals)
        {
            animal.MakeSound();
        }
        // 输出:
        // I am a Dog!
        // I am a Cat!
    }
}
 
interface IAnimal
{
    void MakeSound();
}
 
class Dog : IAnimal
{
    public void MakeSound()
    {
        Console.WriteLine("I am a Dog!");
    }
}
 
class Cat : IAnimal
{
    public void MakeSound()
    {
        Console.WriteLine("I am a Cat!");
    }
}

5. 接口 vs 抽象类

虽然它们都不能实例化,且都被用于被继承,但它们的设计目的不同。

特性 接口 (Interface) 抽象类 (Abstract Class)
继承数量 多继承 (一个类可实现多个接口) 单继承 (一个类只能继承一个抽象类)
成员实现 主要是规范,通常无代码实现 (C# 8.0前) 可以包含已实现的具体方法,也可以包含抽象方法
字段 (Fields) 不能包含字段 (变量) 可以包含字段、常量、静态成员
访问修饰符 默认为 public 可以是 public, protected, private 等
设计理念 “Can Do” (行为):像是一个插件,赋予类某种能力 (如 IDisposable, IEnumerable) “Is A” (本质):定义类的族谱,提取子类的共性

6. 知识拓展:密封类 (Sealed Class)

在面向对象设计中,如果说接口是为了被继承而生,那么密封类就是禁止被继承

关键字:sealed

为什么要用密封类?

  1. 安全性:防止其他开发者随意继承你的类并重写关键功能,导致逻辑破坏。
  2. 性能优化:编译器知道该类不会有子类,可以进行特定的底层优化(如把虚方法调用转换为直接调用)。

语法示例

// 定义一个密封类
sealed class FinalClass
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}
 
// 错误!无法从密封类继承
// class TryToInherit : FinalClass 
// {
// }
 
class Program
{
    static void Main()
    {
        FinalClass fc = new FinalClass(); // 密封类可以被实例化
        Console.WriteLine(fc.Add(1, 2));
    }
}

注意