15.面向对象-继承-里氏替换原则
15.1 知识点
里氏替换原则的基本概念
- 里氏替换原则是面向对象七大原则中最重要的原则
- 概念:任何父类出现的地方,子类都可以替代
- 语法表现:父类容器装子类对象,因为子类对象包含了父类的所有内容
- 作用:方便进行对象存储和管理
里氏替换原则的基本实现
class语句块外 namespace语句块内
//游戏对象类
class GameObject
{
}
//玩家类
class Player : GameObject
{
public void PlayerAtk()
{
Console.WriteLine("玩家攻击");
}
}
//怪物类
class Monster : GameObject
{
public void MonsterAtk()
{
Console.WriteLine("怪物攻击");
}
}
//Boss类
class Boss : GameObject
{
public void BossAtk()
{
Console.WriteLine("Boss攻击");
}
主函数内
//里氏替换原则 用父类容器 装载子类对象
// 父类 变量名 = new 子类();
GameObject player = new Player();
GameObject monster = new Monster();
GameObject boss = new Boss();
GameObject[] objects = new GameObject[] { new Player(), new Monster(), new Boss() };
//Player p = new GameObject();//报错 不能用子类容器装父类对象
is
和 as
主函数内
is 和 as 的基本概念
// is:判断一个对象是否是指定类对象
// 返回值:bool 是为真 不是为假
// as:将一个对象转换为指定类对象
// 返回值:指定类型对象
// 成功返回指定类型对象,失败返回null
is 和 as 的基本语法
// 类对象 is 类名 该语句块 会有一个 bool 返回值 true 和 false
// 类对象 as 类名 该语句块 会有一个对象返回值 对象和 null
is 和 as 的实例
//用is判断容器是GameObject容器的变量player的真实类型是不是Player类
if (player is Player)
{
//用as将变量player转换为容器是Player的对象 用Player容器装
Player p1 = player as Player;
//转换失败会返回空
Player p2 = monster as Player;
//转换成功可以直接使用PlayerAtk()方法
p1.PlayerAtk();
//一步到位的写法
(player as Player).PlayerAtk();
}
//遍历objects数组
for (int i = 0; i < objects.Length; i++)
{
//通过is和as具体判断,转换,转换成功后使用对应子类的内容
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();
}
}
总结
- 概念:父类容器装子类对象
- 作用:方便进行对象的存储和管理
- 使用:
is
和as
用于判断和用于转换 - 注意:不能用子类容器装父类对象
15.2 知识点代码
using System;
namespace Lesson13_继承_里氏替换原则
{
#region 知识点一 里氏替换原则的基本概念
// 里氏替换原则是面向对象七大原则中最重要的原则
// 概念:任何父类出现的地方,子类都可以替代
// 重点:语法表现——父类容器装子类对象,因为子类对象包含了父类的所有内容
// 作用:方便进行对象存储和管理
#endregion
#region 知识点二 里氏替换原则的基本实现
//class语句块外 namespace语句块内
//游戏对象类
class GameObject
{
}
//玩家类
class Player:GameObject
{
public void PlayerAtk()
{
Console.WriteLine("玩家攻击");
}
}
//怪物类
class Monster:GameObject
{
public void MonsterAtk()
{
Console.WriteLine("怪物攻击");
}
}
//Boss类
class Boss:GameObject
{
public void BossAtk()
{
Console.WriteLine("Boss攻击");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("里氏替换原则");
//主函数内
#region 知识点二 里氏替换原则的基本实现
//里氏替换原则 用父类容器 装载子类对象
// 父类 变量名 = new 子类();
GameObject player = new Player();
GameObject monster = new Monster();
GameObject boss = new Boss();
GameObject[] objects = new GameObject[] { new Player(), new Monster(), new Boss() };
//Player p = new GameObject();//报错 不能用子类容器装父类对象
#endregion
#region 知识点三 关键字 is和as
// is和as的基本概念
// is:判断一个对象是否是指定类对象
// 返回值:bool 是为真 不是为假
// as:将一个对象转换为指定类对象
// 返回值:指定类型对象
// 成功返回指定类型对象,失败返回null
//is和as的基本语法
// 类对象 is 类名 该语句块 会有一个bool返回值 true和false
// 类对象 as 类名 该语句块 会有一个对象返回值 对象和null
// is和as的实例
//player.PlayerAtk();
//报错 变量player的真实类型现在是Gameobject 不能直接使用PlayerAtk()方法
//用is 判断容器是Gameobject容器的变量player的真实类型 是不是Player类
if ( player is Player )
{
//用as 将变量player转换为容器是Player的对象 用Player容器装
Player p1 = player as Player;
//转换失败会返回空
Player p2 = monster as Player;
//转换成功可以直接使用PlayerAtk()方法
p1.PlayerAtk();
//一步到位的写法
(player as Player).PlayerAtk();
}
//遍历objects数组
for (int i = 0; i < objects.Length; i++)
{
//通过is和as具体判断,转换,转换成功后使用对应子类的内容
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();
}
}
#endregion
}
}
//总结
//概念:父类容器装子类对象
//作用:方便进行对象的存储和管理
//使用:is和as 用于判断和用于转换
// 注意:不能用子类容器装父类对象
}
15.3 练习题
is和as的区别
is
用于判断一个类对象是否是某一个类型的对象,返回bool
。as
用于尝试将一个类对象转换成指定类型的对象,如果成功返回该类型的对象,否则返回null
。
写一个Monster类,它派生出Boss和Goblin两个类,Boss有技能;小怪有攻击;随机生成10个怪,装载到数组中,遍历这个数组,调用他们的攻击方法,如果是boss就释放技能
class语句块外 namespace语句块内
//怪物类
class Monster
{
}
//Boss类
class Boss : Monster
{
public void Skill()
{
Console.WriteLine("boss技能");
}
}
//哥布林类
class Goblin : Monster
{
public void Atk()
{
Console.WriteLine("哥布林攻击");
}
}
主函数内
// 主函数内
//随机变量
Random r = new Random();
int randomNum;
//声明怪物数组
Monster[] monsters = new Monster[10];
//随机生成10个怪物 装载到怪物数组中
for (int i = 0; i < monsters.Length; i++)
{
randomNum = r.Next(1, 101);
//各百分之50的机会生成boss和哥布林
if (randomNum < 50)
{
monsters[i] = new Boss();
}
else
{
monsters[i] = new Goblin();
}
}
//遍历10个怪物 执行对应子类的攻击方法
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i] is Boss)
{
(monsters[i] as Boss).Skill();
}
else
{
(monsters[i] as Goblin).Atk();
}
}
FPS游戏模拟
写一个玩家类,玩家可以拥有各种武器
现在有四种武器,冲锋枪,散弹枪,手枪,匕首
玩家默认拥有匕首
请在玩家类中写一个方法,可以拾取不同的武器替换自己拥有的武器
class语句块外 namespace语句块内
//武器类
class Weapon
{
}
//冲锋枪
class SubmachineGun : Weapon
{
}
//散弹枪
class ShotGun : Weapon
{
}
//手枪
class Pistol : Weapon
{
}
//匕首
class Dagger : Weapon
{
}
//玩家类
class Player
{
//玩家现在持有的武器
private Weapon nowHaveWeapon;
public Player()
{
//玩家构造时 默认拥有匕首
nowHaveWeapon = new Dagger();
}
//拾取切换武器方法 传入武器 可以是子类
public void PickUp(Weapon weapon)
{
nowHaveWeapon = weapon;
}
}
主函数内
// 主函数内
//创建玩家
Player p = new Player();
//创建冲锋枪
SubmachineGun s = new SubmachineGun();
//拾取冲锋枪
p.PickUp(s);
//创建散弹枪
ShotGun sg = new ShotGun();
//拾取散弹枪
p.PickUp(sg);
15.4 练习题代码
using System;
namespace Lesson13_练习题
{
#region 练习题一
//is和as的区别是什么
// is 用于判断 类对象判断是不是某一个类型的对象 bool
// as 用于转换 把一个类对象 转换成一个指定类型的对象 null
#endregion
//class语句块外 namespace语句块内
#region 练习题二
//写一个Monster类,它派生出Boss和Goblin两个类,
//Boss有技能;小怪有攻击;
//随机生成10个怪,装载到数组中
//遍历这个数组,调用他们的攻击方法,如果是boss就释放技能
//怪物类
class Monster
{
}
//Boss类
class Boss : Monster
{
public void Skill()
{
Console.WriteLine("boss技能");
}
}
//哥布林类
class Goblin:Monster
{
public void Atk()
{
Console.WriteLine("哥布林攻击");
}
}
#endregion
#region 练习题三
//FPS游戏模拟
//写一个玩家类,玩家可以拥有各种武器
//现在有四种武器,冲锋枪,散弹枪,手枪,匕首
//玩家默认拥有匕首
//请在玩家类中写一个方法,可以拾取不同的武器替换自己拥有的武器
//武器类
class Weapon
{
}
//冲锋枪
class SubmachineGun : Weapon
{
}
//散弹枪
class ShotGun : Weapon
{
}
//手枪
class Pistol : Weapon
{
}
//匕首
class Dagger:Weapon
{
}
//玩家类
class Player
{
//玩家现在持有的武器
private Weapon nowHaveWeapon;
public Player()
{
//玩家构造时 默认拥有匕首
nowHaveWeapon = new Dagger();
}
//拾取切换武器方法 传入武器 可以是子类
public void PickUp(Weapon weapon)
{
nowHaveWeapon = weapon;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("里氏替换练习题");
//主函数内
#region 练习题二
//随机变量
Random r = new Random();
int randomNum;
//声明怪物数组
Monster[] monsters = new Monster[10];
//随机生成10个怪物 装载到怪物数组中
for (int i = 0; i < monsters.Length; i++)
{
randomNum = r.Next(1, 101);
//各百分之50的机会生成boss和哥布林
if( randomNum < 50 )
{
monsters[i] = new Boss();
}
else
{
monsters[i] = new Goblin();
}
}
//遍历10个怪物 执行对应子类的攻击方法
for (int i = 0; i < monsters.Length; i++)
{
if( monsters[i] is Boss )
{
(monsters[i] as Boss).Skill();
}
else
{
(monsters[i] as Goblin).Atk();
}
}
#endregion
#region 练习题三
//创建玩家
Player p = new Player();
//创建冲锋枪
SubmachineGun s = new SubmachineGun();
//拾取冲锋枪
p.PickUp(s);
//创建散弹枪
ShotGun sg = new ShotGun();
//拾取散弹枪
p.PickUp(sg);
#endregion
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com