文章目录

C# 接口:interface 定义与实现

发布于 2026-04-02 13:46:19 · 浏览 7 次 · 评论 0 条

C# 接口:interface 定义与实现

在 C# 中,interface(接口)是一种定义行为契约的机制。它规定了类必须实现哪些方法、属性、事件或索引器,但不提供具体实现。通过接口,你可以让多个不相关的类遵循同一套规则,从而提升代码的灵活性和可维护性。


定义一个接口

创建一个接口文件或在现有文件中 定义 接口,使用 interface 关键字。

  1. 新建 一个 .cs 文件(例如 IAnimal.cs)。
  2. 输入 以下代码:
public interface IAnimal
{
    string Name { get; set; }
    void MakeSound();
    bool IsAlive { get; }
}

这段代码定义了一个名为 IAnimal 的公共接口,包含:

  • 一个可读写的字符串属性 Name
  • 一个无返回值的方法 MakeSound()
  • 一个只读布尔属性 IsAlive

注意:接口中的成员不能有访问修饰符(如 publicprivate),因为它们默认就是 public,也不能包含字段或构造函数。


实现接口

一个类 实现 接口,需在类声明时使用冒号 : 后跟接口名,并 提供 所有接口成员的具体实现。

  1. 创建 一个新类(例如 Dog.cs)。
  2. 编写 如下代码:
public class Dog : IAnimal
{
    public string Name { get; set; }
    public bool IsAlive { get; private set; } = true;

    public Dog(string name)
    {
        Name = name;
    }

    public void MakeSound()
    {
        Console.WriteLine($"{Name} says: Woof!");
    }
}
```

这里 `Dog` 类实现了 `IAnimal` 接口:
- **提供了** `Name` 属性的完整 `get` 和 `set`
- **实现了** `MakeSound()` 方法,输出特定声音
- **实现了** `IsAlive` 为只读属性(通过 `private set` 控制写入)

> 如果遗漏任何一个接口成员,编译器会报错:“'Dog' does not implement interface member 'IAnimal.XXX'”。

---

## 多接口实现

一个类可以同时实现多个接口,只需用逗号分隔。

1. **定义** 第二个接口:

```csharp
public interface ITrainable
{
    void Train();
}
```

2. **修改** `Dog` 类以同时实现两个接口:

```csharp
public class Dog : IAnimal, ITrainable
{
    public string Name { get; set; }
    public bool IsAlive { get; private set; } = true;

    public Dog(string name)
    {
        Name = name;
    }

    public void MakeSound()
    {
        Console.WriteLine($"{Name} says: Woof!");
    }

    public void Train()
    {
        Console.WriteLine($"{Name} is learning to sit.");
    }
}
```

现在 `Dog` 同时满足 `IAnimal` 和 `ITrainable` 的契约。

---

## 接口的用途:解耦与多态

使用接口的核心价值在于**解耦调用方与实现方**。你不需要知道对象的具体类型,只要它实现了某个接口,就能安全调用其方法。

1. **编写** 一个通用方法,接受任意 `IAnimal` 对象:

```csharp
public static void LetAnimalSpeak(IAnimal animal)
{
    if (animal.IsAlive)
    {
        animal.MakeSound();
    }
}
```

2. **在主程序中调用**:

```csharp
var dog = new Dog("Buddy");
LetAnimalSpeak(dog); // 输出: Buddy says: Woof!
```

即使将来新增 `Cat`、`Bird` 等类,只要它们实现 `IAnimal`,无需修改 `LetAnimalSpeak` 方法。

---

## 显式接口实现(处理命名冲突)

当两个接口有同名成员时,可使用**显式实现**来区分。

1. **定义** 两个含同名方法的接口:

```csharp
public interface IFlyable
{
    void Move();
}

public interface IWalkable
{
    void Move();
}
```

2. **创建** 一个同时实现两者的类,并显式实现:

```csharp
public class Duck : IFlyable, IWalkable
{
    void IFlyable.Move()
    {
        Console.WriteLine("Duck is flying.");
    }

    void IWalkable.Move()
    {
        Console.WriteLine("Duck is walking.");
    }
}
```

3. **调用时需通过接口类型转换**:

```csharp
var duck = new Duck();
((IFlyable)duck).Move(); // 输出: Duck is flying.
((IWalkable)duck).Move(); // 输出: Duck is walking.
```

显式实现的成员**不能通过类实例直接调用**,只能通过接口引用访问。

---

## 接口继承

接口可以继承其他接口,形成层级结构。

1. **定义** 基础接口:

```csharp
public interface ILivingBeing
{
    bool IsAlive { get; }
}
```

2. **让** `IAnimal` **继承** 它:

```csharp
public interface IAnimal : ILivingBeing
{
    string Name { get; set; }
    void MakeSound();
}
```

现在任何实现 `IAnimal` 的类**必须同时实现** `ILivingBeing` 中的 `IsAlive` 属性。

---

## C# 8.0+ 的默认接口方法(谨慎使用)

从 C# 8.0 起,接口可以包含**默认实现**的方法。

```csharp
public interface IAnimal
{
    string Name { get; set; }
    bool IsAlive { get; }

    void MakeSound()
    {
        Console.WriteLine($"{Name} makes a sound.");
    }
}

此时,实现类可以不重写 MakeSound(),直接使用默认行为。但此特性应谨慎使用,因为它模糊了接口与抽象类的界限,可能破坏“接口仅定义契约”的原则。

若仍要重写,正常实现即可:

public class Cat : IAnimal
{
    public string Name { get; set; }
    public bool IsAlive => true;

    public void MakeSound() // 覆盖默认实现
    {
        Console.WriteLine($"{Name} says: Meow!");
    }
}

最佳实践总结

场景 推荐做法
定义行为契约 使用 interface,避免包含实现细节
多个类共享逻辑 优先考虑组合或抽象类,而非滥用默认接口方法
命名规范 接口名以大写字母 I 开头(如 IRepository
成员设计 只包含 public 成员,不包含字段或构造函数
版本演进 新增成员时尽量不破坏现有实现(C# 8+ 默认方法可缓解此问题)

坚持“面向接口编程”原则:变量、参数、返回值尽可能使用接口类型而非具体类。这能显著提升代码的测试性和扩展性。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文