面向对象三大特性之继承

什么是继承?

    继承是将两个类中相同的属性及方法抽取出来,放到一个新的类中(父类),而这两个子类依然拥有这些属性和方法。抽象点的

    说,每辆车子都能跑(拥有跑的方法),都有轮胎(有轮胎这个属性)。

使用继承编程的好处?

    使用继承编程可以大大的减少代码冗余,增加代码复用。

如何使用继承?

    以第一问为例做延伸:假若我们现在需要两个类,一个货车类,一个轿车类。代码如下

/// <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关键字来指明调用父类的哪个构造函数,则父类必须提供一个默认的构造函数。

欢迎提出意见或建议!!!
原文地址:https://www.cnblogs.com/gaofei-1/p/6429915.html