csharp:类:接口

C# 接口 (Interface) 深度解析

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

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

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

  • 纯粹的规范:接口本身通常不包含实现逻辑(C# 8.0+ 除外),它只规定了类或结构体必须具备的成员(方法、属性、事件、索引器)。
  • 强制实现:一旦一个类继承了某个接口,它必须实现该接口中定义的所有成员,否则编译器会报错。
  • 引用类型:接口是引用类型。虽然不能直接实例化接口(不能 `new Interface()`),但可以声明接口类型的变量,用于指向实现了该接口的类的实例(多态)。
  • 访问修饰符:接口中的成员默认是 public 的。在旧版本 C# 中不允许显式添加修饰符;虽然新版本允许,但通常保持默认。
  • 多继承:C# 的类只能继承一个父类(单继承),但可以实现多个接口。这是接口最强大的功能之一。
  • 层级关系:接口可以继承其他接口,形成接口链。

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

为了实现多态(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!");
    }
}

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

注意:在你提供的示例中,`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}");
    }
}

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

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!");
    }
}

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

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

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

关键字: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));
    }
}

注意

  • 接口 不能 是 sealed 的(因为接口必须被继承才有意义)。
  • 抽象类 不能 是 sealed 的(因为抽象类必须被继承才能实现其抽象方法)。

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • csharp/类/接口.txt
  • 最后更改: 2025/11/27 10:13
  • 张叶安