# 抽象类和接口的区别
概念：
	抽象类和接口都可以用来做抽象，都能配合多态使用
	但它们表达的语义不一样

简单理解：
	抽象类更像“是什么”
	接口更像“能做什么”

例如：
1. `Animal` 抽象类：表示狗、猫、鸟都是动物
2. `IFlyable` 接口：表示某个对象具备飞行能力

----
# 先看抽象类
抽象类：
```csharp
abstract class Animal
{
	public string Name;

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

	public void Eat()
	{
		Console.WriteLine(Name + "吃东西");
	}

	public abstract void Speak();
}
```

子类：
```csharp
class Dog : Animal
{
	public Dog(string name) : base(name)
	{
	}

	public override void Speak()
	{
		Console.WriteLine(Name + "汪汪");
	}
}
```

抽象类适合：
1. 有明确父子关系
2. 要复用公共字段、构造函数、普通方法
3. 还要强制子类实现某些行为

一句话：
	抽象类适合表达“这类东西的共同基础”

----
# 再看接口
接口：
```csharp
interface IFlyable
{
	void Fly();
}
```

实现类：
```csharp
class Bird : IFlyable
{
	public void Fly()
	{
		Console.WriteLine("鸟飞");
	}
}

class Plane : IFlyable
{
	public void Fly()
	{
		Console.WriteLine("飞机飞");
	}
}
```

接口适合：
1. 表达一种能力
2. 多个无关类型都能实现同一种行为
3. 一个类需要同时拥有多种能力
4. 调用方只关心能力，不关心具体身份

一句话：
	接口适合表达“谁能做这件事”

----
# 核心区别
| 对比点 | 抽象类 | 接口 |
|---|---|---|
| 关键词 | `abstract class` | `interface` |
| 主要表达 | 是什么 | 能做什么 |
| 继承数量 | 一个类只能继承一个类 | 一个类可以实现多个接口 |
| 成员实现 | 可以有普通实现，也可以有抽象成员 | 主要规定契约，要求实现类提供成员 |
| 字段 | 可以有字段 | 通常不放实例字段 |
| 构造函数 | 可以有构造函数 | 不能像类一样写实例构造函数 |
| 适合场景 | 提取共同父类和公共代码 | 表达能力、规则、插件式扩展 |
| 多态使用 | 可以用抽象类引用指向子类 | 可以用接口引用指向实现类 |

----
# 单继承和多实现
C# 中：
	一个类只能继承一个父类
	但可以实现多个接口

```csharp
abstract class Character
{
	public string Name;
}

interface IMovable
{
	void Move();
}

interface IAttackable
{
	void Attack();
}

class Player : Character, IMovable, IAttackable
{
	public void Move()
	{
		Console.WriteLine("移动");
	}

	public void Attack()
	{
		Console.WriteLine("攻击");
	}
}
```

理解：
1. `Player` 是一种 `Character`
2. `Player` 同时具备移动能力和攻击能力
3. 父类写一个，接口可以写多个

----
# 什么时候用抽象类
适合用抽象类：
```csharp
abstract class Enemy
{
	public int Hp;

	public void TakeDamage(int damage)
	{
		Hp -= damage;
	}

	public abstract void Attack();
}
```

因为：
1. 小怪、Boss、远程敌人都可以算敌人
2. 它们都有血量、受伤逻辑
3. 它们攻击方式不同

这种情况抽象类很合适：
	有共同身份，也有公共代码

----
# 什么时候用接口
适合用接口：
```csharp
interface IDamageable
{
	void TakeDamage(int damage);
}
```

实现者可能是：
```csharp
class Player : IDamageable
{
	public void TakeDamage(int damage)
	{
	}
}

class Enemy : IDamageable
{
	public void TakeDamage(int damage)
	{
	}
}

class Box : IDamageable
{
	public void TakeDamage(int damage)
	{
	}
}
```

玩家、敌人、箱子不是同一种父类关系，但它们都可以“受伤/受击”。

这种情况接口更合适：
	没有共同身份，但有共同能力

----
# 可以一起用
抽象类和接口不是二选一，经常会一起使用。

```csharp
abstract class Character
{
	public string Name;

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

	public abstract void Update();
}

interface IAttackable
{
	void Attack();
}

class Warrior : Character, IAttackable
{
	public Warrior(string name) : base(name)
	{
	}

	public override void Update()
	{
		Console.WriteLine(Name + "更新状态");
	}

	public void Attack()
	{
		Console.WriteLine(Name + "挥剑攻击");
	}
}
```

理解：
1. `Warrior` 是一种 `Character`
2. `Warrior` 具备 `IAttackable` 能力
3. 抽象类负责共同身份和基础逻辑
4. 接口负责额外能力

----
# 和多态的关系
抽象类多态：
```csharp
Animal animal = new Dog();
animal.Speak();
```

接口多态：
```csharp
IFlyable flyable = new Bird();
flyable.Fly();
```

它们都能做到：
	用统一类型接收不同具体对象
	运行时执行不同实现

区别在于：
1. 抽象类变量强调“它属于某个父类体系”
2. 接口变量强调“它拥有某个能力”

----
# 常见判断方法
问自己几个问题：

1. 这些类是不是同一种东西？
	- 是：优先考虑抽象类
	- 不是：优先考虑接口
2. 是否需要复用字段、构造函数、普通方法？
	- 是：抽象类更合适
3. 一个类是否需要同时拥有多种能力？
	- 是：接口更合适
4. 调用方真正关心的是身份还是能力？
	- 关心身份：抽象类
	- 关心能力：接口

----
# 常见误区
误区1：接口就是更高级的抽象类

不是。
	接口和抽象类不是上下级关系，而是用途不同

----
误区2：有公共方法就一定用抽象类

不一定。
	如果这些类型没有真正的父子关系，硬抽象成父类可能违反[[里氏替换原则]]

----
误区3：接口只能有方法

接口也可以有属性、索引器、事件等成员。
初学阶段先重点掌握方法和属性即可。

----
# 注意
1. 抽象类和接口都不能直接创建对象
2. 抽象类用 `abstract class`，接口用 `interface`
3. 抽象类适合表达共同身份和公共代码
4. 接口适合表达能力和契约
5. 类只能继承一个父类，但可以实现多个接口
6. 抽象类和接口都可以配合多态
7. 设计时先看语义，不要只看语法

----
# 一句话记忆
==抽象类管“是谁的一种”，接口管“能做什么”。==

再压缩一点：
==同类用抽象类，能力用接口。==

----
# 面试/复习时怎么说
可以这样答：

“抽象类和接口都能表达抽象，也都可以配合多态使用。  
抽象类更强调父子关系和公共代码复用，一个类只能继承一个抽象类；接口更强调能力或契约，一个类可以实现多个接口。  
如果多个类本质上是同一种东西，并且有公共字段、构造函数或普通方法，可以用抽象类；如果只是多个类型都有同一种能力，通常用接口更合适。”

----
引用：
1. Microsoft Learn: [abstract (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract)
2. Microsoft Learn: [interface (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface)
3. Microsoft Learn: [Interfaces](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/interfaces)

#抽象类
#接口
#核心
