面向对象-继承
文章目录
- 1、继承的基本规则
- 1、基本概念
- 2、基本语法
- 3、示例
- 4、访问修饰符的影响
- 5、子类和父类的同名成员
- 2、里氏替换原则
- 1、基本概念
- 2、is和as
- 3、基本实现
- 3、继承中的构造函数
- 1、基本概念
- 2、父类的无参构造函数
- 3、通过base调用指定父类构造
- 4、万物之父和装箱拆箱
- 1、万物之父
- 2、万物之父使用
- 3、装箱拆箱
- 5、密封类
- 思考 载具类上下车
1、继承的基本规则
1、基本概念
一个类A继承一个类B类A将会继承类B的所有成员A类将拥有B类的所有特征和行为
被继承的类称为父类、基类、超类
继承的类称为子类。派生类子类可以有自己的特征和行为
特点1、单根性 子类只能有一个父类2、传递性 子类可以间接继承父类的父类
2、基本语法
class 类名 : 被继承的类名{}
3、示例
TeachingTeacher tt = new TeachingTeacher();
tt.name = "亮亮老师";
tt.number = 1;
tt.SpeakName();
tt.subject = "Unity";
tt.SpeakSubject();class Teacher
{public string name;public int number;public void SpeakName(){Console.WriteLine(name);}
}class TeachingTeacher : Teacher
{public string subject;public void SpeakSubject(){Console.WriteLine(subject + "老师");}
}
4、访问修饰符的影响
public 公共 内外部访问
private 私有 内部访问 //子类可以通过父类方法间接访问私有成员
protected 保护 内部和子类访问
internal 内部 只有在同一个程序集的文件中,内部类或者成员才可以访问
5、子类和父类的同名成员
概念:C#中允许子类存在和父类同名的成员,但不建议这样做
2、里氏替换原则
1、基本概念
里氏替换原则是面向对象七大原则中最重要的原则
概念:任何父类出现的地方,子类都可以替代
重点:语法表现-父类容器装子类对象,因为子类对象包含了父类的所以内容
作用:方便进行对象存储和管理
2、is和as
基本概念is:判断一个对象是否是指定类对象返回值:bool 是为真,不是为假as:将一个对象转换为指定类对象返回值:指定类对象成功返回指定类型对象,失败返回null
基本语法:类对象 is 类名该语句块会有一个bool返回值 true 和 false类对象 as 类名该语句块会有一个对象返回值 对象和null
3、基本实现
//里氏替换原则 用父类容器装载子类对象
GameObject player = new Player();
GameObject monster = new Monster();
GameObject boss = new Boss();GameObject[] objects = { player, monster, boss };if(player is Player)
{//Player p = player as Player;//p.PlayerAtk();(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 Monster){(objects[i] as Monster).MonsterAtk();}else if (objects[i] is Boss){(objects[i] as Boss).BossAtk();}
}
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攻击");}
}
3、继承中的构造函数
1、基本概念
特点当声明一个子类对象时先执行父类的构造函数 //执行顺序再执行子类的构造函数
注意父类的无参构造很重要子类可以通过base关键字代表父类,调用父类构造
2、父类的无参构造函数
子类实例化时,默认自动调用父类的无参构造
3、通过base调用指定父类构造
class Father{public Father(int i){}}
class Son : Father{public Son(int i) : base(i){}public Son(int i, sting str):this(i){}
}
4、万物之父和装箱拆箱
1、万物之父
关键字 object
概念object是所有类型的基类,它是一个类(引用类型)
作用1、可以利用里氏替换原则,用object容器装所有对象2、可以用来表示不确定类型,作为函数参数类型
2、万物之父使用
引用类型用is as 来判断和转换class son{Speak(){}}object o = new Son();if(o is son){(o as son).Speak();}
值类型用强转object o = 1.1f;float f = (float)o;
stringobject str = "123abc";string str1 = str.ToString;string str2 = str as string;
数组object arr = new int[10];int[] arr1 =(int[])arr;int[] arr1 =arr as int[];
3、装箱拆箱
发生条件用object存值类型(装箱)再把object转为值类型(拆箱)
装箱把值类型用引用类型存储栈内存会迁移到堆内存中
拆箱把引用类型存储的值类型取出来堆内存会迁移到栈内存中
好处:不确定类型时可以方便参数的存储和传递
坏处:存在内存迁移,增加性能消耗
5、密封类
1、基本概念
密封类是使用sealed密封关键字修饰的类
作用:让类无法再被继承
2、示例
sealed class Father{}
class Son : Father{}
3、作用
再面向对象程序设计中,密封类的主要作用就是不允许最底层子类被继承
可以保证程序的规范性、安全性
思考 载具类上下车
//定义一个载具类
//有速度,最大速度,可乘人数,司机和乘客,有上车,下车方法
//用载具类声明一个对象,并将若干人装载上车Car car = new Car(10, 20, 20);
Driver driver = new Driver();
car.GetIn(driver);
Passenger passenger1 = new Passenger();
car.GetIn(passenger1);
Passenger passenger2 = new Passenger();
car.GetIn(passenger2);
Passenger passenger3 = new Passenger();
car.GetIn(passenger3);
car.GetOff(passenger2);
class Person { }
class Driver : Person { }
class Passenger : Person { }
class Car
{public int speed;public int maxSpeed;public int num;public Person[] persons;public Car(int speed, int maxSpeed, int num){this.speed = speed;this.maxSpeed = maxSpeed;this.num = 0; //实际人数persons = new Person[num];}public void GetIn(Person p){if (num >= persons.Length){Console.WriteLine("满载");return;}persons[num] = p;num++;}public void GetOff(Person p){for (int i = 0; i < persons.Length; i++){if (persons[i] == null){break;}if (persons[i] == p){//移动位置for (int j = i; j < num - 1; j++){persons[j] = persons[j + 1];}//最后一个位置清空persons[num - 1] = null;num--;break;}}}
}