引自于:https://www.bilibili.com/video/BV1wx411K7rb?p=26
注意:在类设计的时候,一定要对成员的访问级别做限制。比如做一个交通工具类,在使用交通工具的时候需要加油和烧油,此时必须要要对烧油这个方法做限制,可以限制为交通工具类及其派生类才能调用的方法,因为这个方法不是谁都能做的,只能是交通工具内部自己操作的,不会由人来操作。尤其是在多人共同做项目的情况下,别人用不到的方法一定不能让开放给别人,避免不必要的问题。
1.继承
(1)继承是单根的,一个基类的变量可以引用其派生类的实例,比如: Vehicle vehicle = new Car();
我们可以说一个交通工具是一个对象,一个车是交通工具,一个车是一个对象,这都是没问题的。
可以看下面代码:
class Program { static void Main(string[] args) { //vehicle是Vehicle的对象,引用的是Car类的实例 Vehicle vehicle = new Car(); // 一个车是一个对象 Object obj = new Car(); //一个交通工具是一个对象 Object objVehicle = new Vehicle(); Console.WriteLine(vehicle is Car); Console.WriteLine(obj is Car); Console.WriteLine(vehicle is Vehicle); Console.ReadKey(); } } /// <summary> /// 交通工具类 /// </summary> class Vehicle { } class Car : Vehicle { }
结果:
True
True
True
(2)sealed类为密封类,不可以被继承,但是一个子类可以继承多个接口
(3)子类的访问级别不能超过基类的访问级别。
注意:
public级别,作用域是整个解决方案。
internal级别,作用域是整个装配集(Assembly),默认不加修饰符的都是internal级别
protected级别,作用域是整个解决方案中以它自己的类为基类以及它的派生类,不在继承链上的类则不能访问
private级别,作用域是它自己的类内部(class)
需要注意的,类成员的访问级别是以类的访问级别为上限的。比如类是internal级别,就算是类内部就public级别的成员,在其他assembly(程序集)中也是看不到这个成员的,因为连这个类都看不到。
继承的本质是派生类在基类已有的成员之上,对基类进行横向和纵向上的扩展。
1.派生类可以继承基类已有的成员。在派生和继承的过程当中,我们进行的是扩展。扩展的意思是在继承过程中,类成员只可能越来越多,不可能越来越少。
也就是说,当把一个成员引用到这个继承链当中,是会一直往下传递,不可能去掉(当然在不运行代码的时候可以直接删掉),所以 要慎重。比如c++,c#,java这些静态语言都是这样的,但是动态语言如javascript可以动态移除添加。
2.横向扩展指的是增加派生类的成员,可以理解成一个人吃的越多越胖。
3.纵向扩展可以理解成不断更新的版本,从基类这个最初的版本向下更新。
4。在继承中,实例构造器是不被继承的。所以基类有构造函数的时候,派生类都不会继承。
看下面代码,首先 ,Car已经创建了一个带参数的构造函数,所以就不会默认创建无参数的构造函数的方法了,所以在实例化的时候必须带参数,否则报错。
其次,在派生类(派生类中初始化了构造函数)实例化的时候会先调用基类的构造函数,然后调用离基类最近的派生类的的构造函数,一直到当前类的构造函数,从上往下。
还有,在派生类中可以使用base调用父类(不是基类)的成员,职称调用离当前类最近的父类的成员,不可能调用父类的父类.....。
class Program { static void Main(string[] args) { //注意:第一点是Car已经创建了一个带参数的构造函数,所以 Car car = new Car("初始车"); RaceCar raceCar = new RaceCar("加速车"); // Console.WriteLine(vehicle is Vehicle); Console.ReadKey(); } } /// <summary> /// 交通工具类 /// </summary> class Vehicle { public string Owner { get; set; } /// <summary> /// 有参数的构造函数,注意,此时Vehicle这个类就不会再默认创建无参数的构造函数了。 /// </summary> /// <param name="owner"></param> public Vehicle(string owner) { Owner = owner; } } class Car : Vehicle { /// <summary> /// 汽车类构造函数 /// </summary> /// <param name="owner"></param> public Car(string owner):base(owner) { } } class RaceCar : Car { /// <summary> /// 汽车类构造函数 /// </summary> /// <param name="owner"></param> public RaceCar(string owner) : base(owner) { } public void Test() { string test = base.Owner; } }
下面代码可以证明car的基类:
namespace 重写多态 { class Program { static void Main(string[] args) { //可以通过下面代码证明Car继承了Vehicle Type type = typeof(Car); Type t = type.BaseType;//寻找继承的基类 Console.WriteLine(t.FullName); Console.ReadKey(); } } //基类 class Vehicle { } class Car : Vehicle { } }
结果:
重写多态.Vehicle