CS3L14——里氏替换原则

里氏替换原则

里氏替换原则是面向对象七大原则中最重要的原则

  • 概念:任何父类出现的地方,子类都可以替代
  • 重点:语法表现为父类容器装子类对象,因为子类对象包含了父类的所有内容
  • 作用:方便进行对象存储和管理

里氏替换原则的意义是:让我们不需要关心子类的实现,只管调用父类声明好的成员即可,它需要配合后续的 多态 才会展现出意义所在

基本实现

注意!用父类容器装载的子类对象不能直接调用子类里的成员方法,如果要使用子类的方法就需要用到 is​ 和 as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class GameObject { }

class Player : GameObject
{
public void PlayerAtk()
{
Console.WriteLine("怪物攻击");
}
}
class Monster : GameObject
{
public void MonsterAtk()
{
Console.WriteLine("怪物攻击");
}
}
class Boss : GameObject
{
public void BossAtk()
{
Console.WriteLine("boss攻击");
}
}

internal class Program
{
static void Main(string[] args)
{
//里氏替换原则 用父类容器 装载 子类对象
GameObject player = new Player();
GameObject monster = new Monster();
GameObject boss = new Boss();

GameObject[] objects = new GameObject[] { new Player(), new Monster(), new Boss() };
}
}

is 和 as

  • is​:判断一个实例化对象是否是指定类

    返回值:bool​ 是为真 不是为假

  • as​:将一个对象转换为指定类

    返回值:指定类型对象,成功返回执行类型对象,返回失败 null

一般 is​ 和 as​ 配合使用,is​ 来确保对象是指定类对象,防止 as​ 返回 null​ 导致报错

as​ 和 括号强转 的区别:

  • 转换检查:括号强转不进行转换检查,直接尝试转换。as​ 会先进行转换检查,如果对象不能转换为目标类型,则返回null
  • 失败处理:括号强转如果转换失败,会抛出InvalidCastException​异常。as​ 不会抛出异常,而是返回null
  • 适用范围:括号强转可以用于值类型和引用类型。as​ 只能用于引用类型和可空值类型(如int?​),不能用于非可空值类型

基本语法:

  • 类对象 is 类名​ 该语句 会返回一个 bool​ 值:false​ 或者 true
  • 类对象 as 类名​ 该语句 会有一个对象返回值对象或者 null

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class GameObject { }

class Player : GameObject
{
public void PlayerAtk()
{
Console.WriteLine("怪物攻击");
}
}
class Monster : GameObject
{
public void MonsterAtk()
{
Console.WriteLine("怪物攻击");
}
}
class Boss : GameObject
{
public void BossAtk()
{
Console.WriteLine("boss攻击");
}
}

internal class Program
{
static void Main(string[] args)
{
GameObject player = new Player();
GameObject[] objects = new GameObject[] { new Player(), new Monster(), new Boss() };

if (player is Player)
{
Console.WriteLine("是Player类型的");
(player as Player).PlayerAtk();
}

//一般is和as配合使用,is来确保对象是指定类对象,防止as返回null导致报错
for (int i = 0; i < objects.Length; i++)
{
if (objects[i] is Player)
{
(objects[i] as Player).PlayerAtk();
}
else if (objects[i] is Monster)
{
(objects[i] as Monster).MonsterAtk();
}
else if (objects[i] is Boss)
{
(objects[i] as Boss).BossAtk();
}
}
}
}