一.继承:继承的基本规则
1.基本概念
一个类A继承一个类B
类A将继承类B的所有成员
A类将拥有B类的所有特征和行为
被继承的类
称为 父类,基类,超类
继承的类
称为 子类,派生类
子类可以有自己的特征和行为
·特点
1.单根性 子类只能有一个父类
2.传递性 子类可以间接继承父类的父类
2.基本语法
class 类名 : 被继承的类名
{
}
3.实例
class Teacher
{
public int number;
public string name;
public void speak()
{
Console.WriteLine("My name is {0},number is{1}",name,number);
}
}
class TeachingTeacher : Teacher
{
public string subject;
public void Teaching()
{
Console.WriteLine(subject + "老师" + name);
}
}
TeachingTeacher tt = new TeachingTeacher();
tt.name = "老王";
tt.number = 1;
tt.speak();
tt.Teaching();
4.访问修饰符的影响(protected)
public - 公共的 内外部访问
private - 私有 内部访问
protected - 保护 内部和子类访问
internal - 内部的 只有在同一个程序的文件中,内部类行或者是成员才可以访问
private | protected |
不能在外部使用 | |
不能在子类中使用 | 能在子类中使用 |
五.子类和同名成员
C#允许子类中存在与父类成员同民的成员,但极不建议使用
当子类存在与父类同名的成员时会将该父类成员隐藏
二.里氏替换原则
1.里氏替换原则是面向对象七大原则中最重要的原则
概念:
任何父类出现的地方,子类都可以替代
重点:
语法表现——父类容装子类对象,因为子类对象包含了父类的所有内容
作用:
方便进行对象储存和管理
class GameObject
{
}
class Player:GameObject
{
int ATK;
public void PlayerAtk()
{
Console.WriteLine("玩家攻击");
}
}
class Monstor : GameObject
{
public void MonsterAtack()
{
Console.WriteLine("怪物攻击");
}
}
class Npc : GameObject
{
public void Chat()
{
Console.WriteLine("打架先踢蛋 事先赢一半");
}
}
主函数中实现
//在子函数中用父类装载子类对象
GameObject player = new Player();
GameObject Monstor = new Monstor();
GameObject Boss = new Npc();
GameObject[] objects = new GameObject[] { new Player(), new Monstor(), new Npc() };
2.is 和 as
为了解决在使用父类时不能调用成员方法的问题,使用is 和 as
【1】is : 判断个对象是否是指定类对象
返回值:bool
if (player is Player)
{
}
【2】as : 将─个对象转换为指定类的对象
返回值:指定类型对象
Player p = monstor as Player;
成功返回执行类型对象,失败返回null
【3】基本语法
类对象is类名该语句块会有会有一个bool返回值true和false
类对象as类名该语句块会有会有一个对象返回值对象和null
if (player is Player)
{
Player p1 = player as Player;
p1.PlayerAtk();
}
便捷写法调用
if (player is Player)
{
(player as Player).PlayerAtk();
}
for (int i = 0; i < objects.Length; i++)
{
if( objects[i] is Player)
{
(objects[i] as Player).PlayerAtk();
}
else if(objects[i] is Monstor)
{
(objects[i] as Monstor).MonsterAtack();
}
else
{
(objects[i] as Npc).Chat();
}
}
利用里氏替换原则实现随机生成怪物并使其使用自生的方法
Random r = new Random();
int randomNum;
//随机生成十个怪物
Monster[] monsters = new Monster[10];
for (int i = 0; i < monsters.Length; i++)
{
randomNum = r.Next(1, 101);
if (randomNum < 50)
{
monsters[i] = new Boss();
}
else
{
monsters[i] = new Goblin();
}
}
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i] is Boss)
{
(monsters[i] as Boss).Skill();
}
else
{
(monsters[i] as Goblin).Atk();
}
}
继承中的构造函数
//申明子类后,先执行子类构造函数,再执行子类的构造函数
//注意:
//1.父类无参构造函数很重要
//2.子类可以通过base关键字 代表父类 调用父类的构造
//执行顺序 自上而下
//父类无参构造函数很重要(子类在被实例化时,默认先执行父类的无参构造)
class Father
{
public Father()
{
}
public Father(int i)
{
}
}
//当父类无参构造函数被有参函数顶掉时,会报错
class Son : Father
{
public Son( int i ) : base()
{
}
}
万物之父和装箱拆箱
回顾里氏替换原则
概念:父类容器容装子类对象
作用:方便进行对象存储和管理
使用:
is和as
is用于判断
as用于转换
万物之父
关键字object
概念:object是所有类型的基类,它是一个类(引用类型)
利用里氏替换原则,可以用object容装所有对象
可用于表示不确定类型,作为函数的参数类型