面向对象三大特性之继承
什么是继承?
继承是将两个类中相同的属性及方法抽取出来,放到一个新的类中(父类),而这两个子类依然拥有这些属性和方法。抽象点的
说,每辆车子都能跑(拥有跑的方法),都有轮胎(有轮胎这个属性)。
使用继承编程的好处?
使用继承编程可以大大的减少代码冗余,增加代码复用。
如何使用继承?
以第一问为例做延伸:假若我们现在需要两个类,一个货车类,一个轿车类。代码如下
/// <summary> 2 /// 货车类 3 /// </summary> 4 class Truck 5 { 6 //时速 7 public int Speed { get; set; } 8 //颜色 9 public string Colour { get; set; } 10 //购买价格 11 public double Price { get; set; } 12 13 /// <summary> 14 /// 货运方法 15 /// </summary> 16 public void Cargo() 17 { 18 Console.WriteLine("运输货物"); 19 } 20 } 21 22 /// <summary> 23 /// 轿车类 24 /// </summary> 25 class Sedan 26 { 27 //时速 28 public int Speed { get; set; } 29 //颜色 30 public string Colour { get; set; } 31 //购买价格 32 public double Price { get; set; } 33 34 /// <summary> 35 /// 载客方法 36 /// </summary> 37 public void CarryPassengers() 38 { 39 Console.WriteLine("载客"); 40 } 41 }
通过这段代码不难发现,货车类和轿车类拥有三个相同的属性,一个不同的方法。根据继承的特性,需要把相同的属性或方法抽
取出来。代码如下
/// <summary> 2 /// 车辆类 父类 3 /// </summary> 4 class Vehicle 5 { 6 //时速 7 public int Speed { get; set; } 8 //颜色 9 public string Colour { get; set; } 10 //购买价格 11 public double Price { get; set; } 12 } 13 14 /// <summary> 15 /// 货车类 继承车辆类 16 /// </summary> 17 class Truck : Vehicle 18 { 19 /// <summary> 20 /// 货运方法 21 /// </summary> 22 public void Cargo() 23 { 24 Console.WriteLine("运输货物"); 25 } 26 } 27 28 /// <summary> 29 /// 轿车类 继承车辆类 30 /// </summary> 31 class Sedan : Vehicle 32 { 33 /// <summary> 34 /// 载客方法 35 /// </summary> 36 public void CarryPassengers() 37 { 38 Console.WriteLine("载客"); 39 } 40 }
那么问题又来了,继承的特性-代码复用体现在哪里呢?下面我们简单地了解一下。
在第一段代码中,有两个类,如果我们想在创建对象时使用带参构造函数来初始化属性的话,要在两个类中都写上相同的一段代
码。(构造函数详解)
1 /// <summary> 2 /// 货车类 3 /// </summary> 4 class Truck 5 { 6 //时速 7 public int Speed { get; set; } 8 //颜色 9 public string Colour { get; set; } 10 //购买价格 11 public double Price { get; set; } 12 public Truck(int speed, string colour, double price) 13 { 14 this.Speed = speed; 15 this.Colour = colour; 16 this.Price = price; 17 } 18 ... 19 } 20 21 /// <summary> 22 /// 轿车类 23 /// </summary> 24 class Sedan 25 { 26 //时速 27 public int Speed { get; set; } 28 //颜色 29 public string Colour { get; set; } 30 //购买价格 31 public double Price { get; set; } 32 public Truck(int speed, string colour, double price) 33 { 34 ... 35 } 36 ... 37 }
显而易见,上面的重复代码很多。下面我们使用继承来简化一下上面的代码。
1 /// <summary> 2 /// 车辆类 父类 3 /// </summary> 4 class Vehicle 5 { 6 //时速 7 public int Speed { get; set; } 8 //颜色 9 public string Colour { get; set; } 10 //购买价格 11 public double Price { get; set; } 12 13 /// <summary> 14 /// 带参构造函数 15 /// </summary> 16 /// <param name="speed"></param> 17 /// <param name="colour"></param> 18 /// <param name="price"></param> 19 public Vehicle(int speed, string colour, double price) 20 { 21 this.Speed = speed; 22 this.Colour = colour; 23 this.Price = price; 24 } 25 } 26 27 /// <summary> 28 /// 货车类 继承车辆类 29 /// </summary> 30 class Truck : Vehicle 31 { 32 /// <summary> 33 /// 子类使用父类构造函数 34 /// </summary> 35 public Truck(int speed, string colour, double price) : 36 base (speed,colour,price) 37 { 38 39 } 40 ... 41 } 42 43 /// <summary> 44 /// 轿车类 继承车辆类 45 /// </summary> 46 class Sedan : Vehicle 47 { 48 /// <summary> 49 /// 子类使用父类构造函数 50 /// </summary> 51 public Sedan(int speed, string colour, double price) : 52 base (speed,colour,price) 53 { 54 55 } 56 ... 57 }
使用了继承之后,即使再多的派生类需要带参构造函数,也不怕了,只要一行代码即可完成。
Base关键字:
base关键字表示父类,可以用于访问父类的成员。例:base.父类成员。
除了上面通过base显示的调用父类带参构造函数外,创建子类对象时还会隐式的调用父类的无参构造函数。(创建子类对象时
会先调用父类的无参构造函数。)
进一步了解和使用继承
继承的特性:
1.传递性:继承可以无限的向下派生,但是需要符合一个条件:子类可以出现在父类出现的地方并替换父类,即子类
拥有父类的全部特征和能够实现父类的全部方法。
2.单根性:一个子类只能继承自一个父类。不存在一个子类同时继承自两个或多个父类的情况。
is a关键字:
这个关键字用来判断对象是否属于给定的类型。返回值为bool类型。
例:
if (Vehicle is Truck)
{
...
}
sealed关键字:
用这个关键字修饰的类是不能被继承的,即密封类。常用的string类就是密封类。本文只做了解,后更示例。
至此,关于继承已经讲得差不多了,下面是本文用到的所有代码,希望可以帮到看到此处的你。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Demo demo = new Demo(); 6 demo.Test(); 7 8 Console.Read(); 9 } 10 } 11 12 class Demo 13 { 14 List<Vehicle> vehicles = new List<Vehicle>(); 15 16 public void Test() 17 { 18 vehicles.Add(new Truck(50, "蓝色", 150000)); 19 vehicles.Add(new Sedan(80, "黑色", 210000)); 20 foreach (Vehicle item in vehicles) 21 { 22 if (item is Truck) 23 { 24 Console.WriteLine("我是货车,时速{0},我是{1}的,价格{2}元。", item.Speed, item.Colour, item.Price); 25 ((Truck)item).Cargo(); 26 } 27 if (item is Sedan) 28 { 29 Console.WriteLine("我是轿车,时速{0},我是{1}的,价格{2}元。",item.Speed,item.Colour,item.Price); 30 ((Sedan)item).CarryPassengers(); 31 } 32 } 33 } 34 } 35 36 /// <summary> 37 /// 车辆类 父类 38 /// </summary> 39 class Vehicle 40 { 41 //时速 42 public int Speed { get; set; } 43 //颜色 44 public string Colour { get; set; } 45 //购买价格 46 public double Price { get; set; } 47 48 /// <summary> 49 /// 带参构造函数 50 /// </summary> 51 /// <param name="speed"></param> 52 /// <param name="colour"></param> 53 /// <param name="price"></param> 54 public Vehicle(int speed, string colour, double price) 55 { 56 this.Speed = speed; 57 this.Colour = colour; 58 this.Price = price; 59 } 60 } 61 62 /// <summary> 63 /// 货车类 继承车辆类 64 /// </summary> 65 class Truck : Vehicle 66 { 67 /// <summary> 68 /// 子类使用父类构造函数 69 /// </summary> 70 public Truck(int speed, string colour, double price) : 71 base (speed,colour,price) 72 { 73 74 } 75 76 /// <summary> 77 /// 货运方法 78 /// </summary> 79 public void Cargo() 80 { 81 Console.WriteLine("我能运输货物"); 82 } 83 } 84 85 /// <summary> 86 /// 轿车类 继承车辆类 87 /// </summary> 88 class Sedan : Vehicle 89 { 90 /// <summary> 91 /// 子类使用父类构造函数 92 /// </summary> 93 public Sedan(int speed, string colour, double price) : 94 base (speed,colour,price) 95 { 96 97 } 98 /// <summary> 99 /// 载客方法 100 /// </summary> 101 public void CarryPassengers() 102 { 103 Console.WriteLine("我可以载客"); 104 } 105 }
结尾语:学到知识不与人分享,犹如衣锦夜行,毫无意义。
2017-02-23 22:02:34补充
as关键字:
as关键字可以进行对象之间的类型转换,可以替代强制类型转换。和强制类型转换不同的是,使用as关键字类进行类型
转换如果转换失败会返回null,不会产生异常;而强制类型转换在转换失败时会产生异常。
语法:
父类 as 子类
重载构造函数:
如果子类重载的构造函数没有使用base关键字来指明调用父类的哪个构造函数,则父类必须提供一个默认的构造函数。