差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 后一修订版 | 前一修订版 | ||
| csharp:类:接口 [2025/09/28 16:50] – 创建 张叶安 | csharp:类:接口 [2025/11/27 10:13] (当前版本) – [语法示例] 张叶安 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | # 接口简介 | + | ====== C# 接口 |
| - | 关键字interface(int fei s) | + | 接口(Interface)是 C# 面向对象编程中非常核心的概念。它定义了“行为的规范”,起到了强制契约的作用。 |
| - | 1:接口本身不包含任何实现逻辑,它仅仅是规定了要实现它的类或结构必须遵循的蓝图。 | + | ===== 1. 接口简介 ===== |
| - | 2:接口是一种规范、只要一个类继承了接口、就要实现这个接口中的所有成员! | + | **关键字**:%%interface%% (读音: /' |
| - | 3:抽象类与接口都是被其他类继承\通过创建接口父类的对象来指向子类! | + | 接口定义了所有类继承接口时应遵循的**语法合同**。接口定义了“**是什么**”(规范),而不关心“**怎么做**”(实现)。 |
| - | 4:接口中的成员不允许添加访问修饰符,默认就是public | + | ==== 核心特性 ==== |
| - | 5:接口与接口之间可以继承、且可以多继承、 | + | * **纯粹的规范**:接口本身通常不包含实现逻辑(C# |
| + | * **强制实现**:一旦一个类继承了某个接口,它**必须**实现该接口中定义的所有成员,否则编译器会报错。 | ||
| + | * **引用类型**:接口是引用类型。虽然不能直接实例化接口(不能 `new Interface()`),但可以声明接口类型的变量,用于指向实现了该接口的类的实例(多态)。 | ||
| + | * **访问修饰符**:接口中的成员默认是 **public** 的。在旧版本 C# 中不允许显式添加修饰符;虽然新版本允许,但通常保持默认。 | ||
| + | * **多继承**:C# 的类只能继承一个父类(单继承),但**可以实现多个接口**。这是接口最强大的功能之一。 | ||
| + | * **层级关系**:接口可以继承其他接口,形成接口链。 | ||
| - | 6: 接口不能去继承一个类、而类可以继承接口、 | ||
| + | **记忆口诀**:接口像是一个“职位描述(JD)”,类像是“员工”。JD 规定了员工必须会做什么(比如会编程、会英语),但具体怎么编程、怎么说英语,由员工(类)自己决定。 | ||
| - | 9:为了多态、接口不能被new实例化! | ||
| - | 但可以用来定义变量、以便用来引用、继承的子类成员、例如: | + | ===== 2. 基础语法与多态 ===== |
| - | ``` | + | 为了实现多态(Polymorphism),我们通常使用**接口类型的变量**来引用**子类的对象**。 |
| - | class Program | + | |
| + | <code csharp> | ||
| + | class Program | ||
| { | { | ||
| static void Main(string[] args) | static void Main(string[] args) | ||
| { | { | ||
| - | // 使用接口类型的变量来引用实现了接口的对象 | + | // 多态的核心:左边是接口,右边是具体实现类 |
| - | IAnimal myDog = new Dog(); | + | // IAnimal myDog = new IAnimal(); // 错误!接口不能被实例化 |
| - | // 调用接口的方法,实际执行的是具体对象的方法 | + | |
| + | IAnimal myDog = new Dog(); | ||
| + | | ||
| + | // 调用接口的方法,实际执行的是 | ||
| myDog.MakeSound(); | myDog.MakeSound(); | ||
| } | } | ||
| } | } | ||
| - | // 定义一个接口 | + | |
| + | // 1. 定义接口 | ||
| interface IAnimal | interface IAnimal | ||
| { | { | ||
| - | void MakeSound(); | + | void MakeSound(); |
| } | } | ||
| - | // 继承于接口的Dog类 | + | |
| + | // 2. 实现接口 | ||
| class Dog : IAnimal | class Dog : IAnimal | ||
| { | { | ||
| - | | + | // 必须实现接口中的所有方法,且必须是 public |
| + | public void MakeSound() | ||
| { | { | ||
| - | Console.WriteLine(" | + | Console.WriteLine(" |
| } | } | ||
| } | } | ||
| - | ``` | + | </ |
| - | # 接口举例1 | + | ===== 3. 接口成员:属性与方法 ===== |
| - | 接口是一种规范、只要一个类继承了接口、就要实现这个接口中的所有成员! | + | 接口不仅可以定义方法,还可以定义属性。 |
| - | ``` | + | **注意**:在你提供的示例中,`Main` 函数尝试给属性赋值,但接口定义中只有 |
| + | |||
| + | <code csharp> | ||
| class Program | class Program | ||
| + | { | ||
| + | static void Main(string[] args) | ||
| { | { | ||
| - | | + | // 实例化实现类 |
| - | { //实例化派生类 | + | |
| - | | + | |
| - | //使用 | + | |
| - | syong.Name = " | + | syong.Name = "智能手机"; |
| - | syong.Codr = " | + | syong.Code = " |
| - | syong.ShowInfo(); | + | |
| - | } | + | // 调用方法 |
| + | | ||
| } | } | ||
| - | | + | } |
| - | interface | + | |
| + | // 定义接口 | ||
| + | interface | ||
| + | { | ||
| + | // 接口中的属性通常指明需要 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 | ||
| { | { | ||
| - | | + | |
| - | | + | |
| - | void ShowInfo();// | + | |
| } | } | ||
| - | | + | |
| - | | + | |
| + | public | ||
| { | { | ||
| - | | + | |
| - | | + | |
| + | } | ||
| - | public string Codr | + | |
| - | { | + | |
| - | get | + | |
| - | { | + | |
| - | return str_1; | + | |
| - | } | + | |
| - | } | + | |
| - | public string Name | + | |
| - | { | + | |
| - | get | + | |
| - | { | + | |
| - | return str_2; | + | |
| - | } | + | |
| - | } | + | |
| - | public void ShowInfo() | + | |
| - | { | + | |
| - | // | + | |
| - | } | + | |
| } | } | ||
| - | ``` | + | } |
| + | </ | ||
| - | # 接口举例2 | + | ===== 4. 接口的多态性 (进阶举例) ===== |
| - | # 接口的多态举例 | + | 这是接口最常见的应用场景:**统一管理不同的对象**。 |
| - | ``` | + | |
| + | <code csharp> | ||
| using System; | using System; | ||
| + | |||
| class Program | class Program | ||
| { | { | ||
| static void Main(string[] args) | static void Main(string[] args) | ||
| { | { | ||
| - | // 使用接口类型的变量来引用实现了接口的对象 | + | // 使用接口数组或集合,可以同时管理 Dog 和 Cat |
| - | IAnimal | + | IAnimal[] animals = new IAnimal[2]; |
| - | | + | |
| + | animals[0] | ||
| + | | ||
| - | // 调用接口的方法,实际执行的是具体对象的方法 | + | // 遍历集合,虽然都是 IAnimal 类型,但表现出不同的行为 |
| - | | + | |
| - | | + | { |
| + | animal.MakeSound(); | ||
| + | } | ||
| + | | ||
| + | // I am a Dog! | ||
| + | // I am a Cat! | ||
| } | } | ||
| } | } | ||
| - | // 定义一个接口 | ||
| interface IAnimal | interface IAnimal | ||
| { | { | ||
| void MakeSound(); | void MakeSound(); | ||
| } | } | ||
| - | // 继承于接口的类Dog | + | |
| class Dog : IAnimal | class Dog : IAnimal | ||
| { | { | ||
| - | public void MakeSound()// | + | public void MakeSound() |
| { | { | ||
| - | Console.WriteLine(" | + | Console.WriteLine(" |
| } | } | ||
| } | } | ||
| - | // 继承于接口的类Cat | + | |
| class Cat : IAnimal | class Cat : IAnimal | ||
| { | { | ||
| - | public void MakeSound()// | + | public void MakeSound() |
| { | { | ||
| - | Console.WriteLine(" | + | Console.WriteLine(" |
| } | } | ||
| } | } | ||
| - | ``` | + | </ |
| - | 总接:一个/ | + | ===== 5. 接口 vs 抽象类 ===== |
| - | 就可以用接口定义的变量来引用[点]子类里面实现接口成员的函数、 | + | 虽然它们都不能实例化,且都被用于被继承,但它们的设计目的不同。 |
| + | ^ 特性 ^ 接口 (Interface) ^ 抽象类 (Abstract Class) ^ | ||
| + | | **继承数量** | **多继承** (一个类可实现多个接口) | **单继承** (一个类只能继承一个抽象类) | | ||
| + | | **成员实现** | 主要是规范,通常无代码实现 (C# 8.0前) | 可以包含已实现的具体方法,也可以包含抽象方法 | | ||
| + | | **字段 (Fields)** | 不能包含字段 (变量) | 可以包含字段、常量、静态成员 | | ||
| + | | **访问修饰符** | 默认为 public | 可以是 public, protected, private 等 | | ||
| + | | **设计理念** | **"Can Do"** (行为):像是一个插件,赋予类某种能力 (如 IDisposable, | ||
| - | # 抽象类与接口的区别 | + | ===== 6. 知识拓展:密封类 (Sealed Class) ===== |
| - | 1:接口与抽象类都不能被实例化、只能被继承 | + | 在面向对象设计中,如果说接口是**为了被继承**而生,那么密封类就是**禁止被继承**。 |
| - | 2: | + | **关键字**:%%sealed%% |
| - | 3:抽象类也规范了一些成员、继承抽象类就要重写它的成员、 | + | ==== 为什么要用密封类? ==== |
| + | - **安全性**:防止其他开发者随意继承你的类并重写关键功能,导致逻辑破坏。 | ||
| + | - **性能优化**:编译器知道该类不会有子类,可以进行特定的底层优化(如把虚方法调用转换为直接调用)。 | ||
| - | {{.:pasted: | + | ==== 语法示例 ==== |
| + | |||
| + | <code csharp> | ||
| + | // 定义一个密封类 | ||
| + | sealed class FinalClass | ||
| + | { | ||
| + | public int Add(int a, int b) | ||
| + | | ||
| + | return a + b; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // 错误!无法从密封类继承 | ||
| + | // class TryToInherit | ||
| + | // { | ||
| + | // } | ||
| + | |||
| + | class Program | ||
| + | { | ||
| + | static void Main() | ||
| + | { | ||
| + | FinalClass fc = new FinalClass(); | ||
| + | Console.WriteLine(fc.Add(1, 2)); | ||
| + | | ||
| + | } | ||
| + | </ | ||
| - | 90-60:知识拓展密封类 | ||
| - | {{.: | + | **注意**: |
| + | * 接口 **不能** 是 sealed 的(因为接口必须被继承才有意义)。 | ||
| + | * 抽象类 **不能** 是 sealed 的(因为抽象类必须被继承才能实现其抽象方法)。 | ||