C#面向对象之继承

一、继承

  什么是继承?继承是两个或多个类之间存在的依赖关系,其中被继承的类称为父类或基类,继承的类称为子类或派生类。在继承关系中,父类是对子类的共性提取,子类是对父类的扩展。

 1 /// <summary>
 2 /// 文字
 3 /// </summary>
 4 public class Word
 5 {
 6     /// <summary>
 7     /// 内容
 8     /// </summary>
 9     public string Content { get; set; }
10     /// <summary>
11     /// 大小(单位B)
12     /// </summary>
13     public int Size { get; set; }
14 
15     public Word() { }
16     public Word(string content, int size)
17     {
18         this.Content = content;
19         this.Size = size;
20     }
21 }
22 /// <summary>
23 /// 图片
24 /// </summary>
25 public class Picture
26 {
27     /// <summary>
28     /// 内容
29     /// </summary>
30     public string Content { get; set; }
31     /// <summary>
32     /// 大小(单位B)
33     /// </summary>
34     public int Size { get; set; }
35     /// <summary>
36     /// 地址
37     /// </summary>
38     public string Path { get; set; }
39 
40     public Picture() { }
41     public Picture(string content, int size, string path)
42     {
43         this.Content = content;
44         this.Size = size;
45         this.Path = path;
46     }
47 
48     /// <summary>
49     /// 图片存储到文件中,并为Path赋值
50     /// </summary>
51     public void StoreToFile()
52     {
53 
54     }
55 }

上面设计的文字类和图片类中存在代码冗余,为了去除冗余,我通过提取共性的方式引入了第三个类,并让其他两个类继承它,代码如下:

 1 /// <summary>
 2 /// 信息
 3 /// </summary>
 4 public class Information
 5 {
 6     /// <summary>
 7     /// 内容
 8     /// </summary>
 9     public string Content { get; set; }
10     /// <summary>
11     /// 大小(单位B)
12     /// </summary>
13     public int Size { get; set; }
14 
15     public Information() { }
16     public Information(string content, int size)
17     {
18         this.Content = content;
19         this.Size = size;
20     }
21 }
22 /// <summary>
23 /// 文字
24 /// </summary>
25 public class Word : Information
26 {
27     public Word() { }
28     public Word(string content, int size)
29     {
30         this.Content = content;
31         this.Size = size;
32     }
33 }
34 /// <summary>
35 /// 图片
36 /// </summary>
37 public class Picture : Information
38 {
39     /// <summary>
40     /// 地址
41     /// </summary>
42     public string Path { get; set; }
43 
44     public Picture() { }
45     public Picture(string content, int size, string path)
46     {
47         this.Content = content;
48         this.Size = size;
49         this.Path = path;
50     }
51 
52     /// <summary>
53     /// 图片存储到文件中,并为Path赋值
54     /// </summary>
55     public void StoreToFile()
56     {
57 
58     }
59 }
60 /// <summary>
61 /// 实现对象
62 /// </summary>
63 public class RealizeObject
64 {
65     public void Realize()
66     {
67         //Word类和Picture类继承Information类后,Information类的Content和Size属性就像Word类和Picture类的属性一样
68         Word word = new Word("book", 4);
69         Picture picture = new Picture("", 0, @"C:\Users\Images\");
70         Information info = new Information("this is Info", 12);
71     }
72 }

通过继承连接文字/图片类和它们提取共性的信息类,实现了代码的复用性,后期如果加上音频类和视频类也可以通过继承复用信息类的代码,而不用重复编写Content和Size属性。

 

继承的规则:

1、子类可以继承除了父类构造函数之外的所有非私有成员。

2、子类的任意构造函数调用之前会先调用父类的默认构造函数。

3、子类的可访问性不能高于父类,因为这样会强制父类的可访问性同子类的可访问性(比如Word用public修饰,Information用internal修饰)。

4、C#不允许类的多重继承,即一个类只能有一个直接父类(继承引号符后面只能写一个类)。

 

根据继承规则二,总结继承中代码的执行顺序:执行变量的初始化表达式 → 执行父类的(默认)构造函数 → 调用类型自己的构造函数

 1 public class A
 2 {
 3     public To t = new To("TO A");
 4 
 5     public A()
 6     {
 7         Console.WriteLine("A");
 8     }
 9 }
10 public class B : A
11 {
12     public To t = new To("TO B");
13 
14     public B()
15     {
16         Console.WriteLine("B");
17     }
18 }
19 public class C : B
20 {
21     public To t = new To("TO C");
22 
23     public C()
24     {
25         Console.WriteLine("C");
26     }
27 }
28 public class To
29 {
30     public To(string msg)
31     {
32         Console.WriteLine(msg);
33     }
34 }
35 public class RealizeObject
36 {
37     public void Realize()
38     {
39         C c = new C();
40         //输出结果是:
41         //TO C
42         //TO B
43         //TO A
44         //A
45         //B
46         //C
47     }
48 }

 

二、C#关键字:base

  继承的规则一说明子类无法使用父类的构造函数,所以我在文字类和图片类中创建了自己的构造函数。继承的规则二说明子类只能隐式地调用父类的默认构造函数,而无法调用父类的非默认构造函数,即无法复用父类的非默认构造函数,所以可以通过base关键字使子类的构造函数自定义调用父类的非默认构造函数。下面修改文字类和图片类使其复用父类的非默认构造函数:

 1 /// <summary>
 2 /// 文字
 3 /// </summary>
 4 public class Word : Information
 5 {
 6     public Word() { }
 7     public Word(string content, int size) : base(content, size);
 8 }
 9 /// <summary>
10 /// 图片
11 /// </summary>
12 public class Picture : Information
13 {
14     /// <summary>
15     /// 地址
16     /// </summary>
17     public string Path { get; set; }
18 
19     public Picture() { }
20     public Picture(string content, int size, string path)
21         : base(content, size)
22     {
23         this.Path = path;
24     }
25 
26     /// <summary>
27     /// 图片存储到文件中,并为Path赋值
28     /// </summary>
29     public void StoreToFile()
30     {
31 
32     }
33 }

base关键字除了可以复用父类非默认构造函数之外,还可以复用父类的其他非私有成员(见C#多态)。

总结:base关键字的使用方式同this关键字一样,区别在于this关键字指向本类,base关键字指向父类。

 

三、C#关键字:sealed

  sealed关键字可以防止被继承或者被重写。

1 /// <summary>
2 /// 视频类(不能被其他类继承)
3 /// </summary>
4 public sealed class Video : Information { }

  注:sealed在防止被继承时多用于工具类。

  sealed防止被重写(见C#多态)。

 

四、C#关键字:protected

  protected是专门用于继承中的访问修饰符,修饰在父类的成员上使其成员可被本类及其子类访问。

  注:protected多用于修饰父类的方法。

  访问修饰符直白对比:对全世界开放,使用public;只对本国开放,使用internal;只对家族开放,使用protected;只有自己知道,使用private。

 

五、类型之间的关系:包含

  C#五大类型(类、接口、委托、枚举、结构)之间的相互嵌套即包含关系。既可以包含已定义类型也可以直接在被包含类型内定义类型。

  包含的作用同继承一样也是提高代码的复用性。

 1 /// <summary>
 2 /// 洗衣机类
 3 /// </summary>
 4 public class WashingMachine
 5 {
 6 
 7 }
 8 /// <summary>
 9 /// 房间类
10 /// </summary>
11 public class House
12 {
13     /// <summary>
14     /// 房间类包含已定义的洗衣机类
15     /// </summary>
16     public WashingMachine washingMachine { get; set; }
17 
18     /// <summary>
19     /// 直接在房间类中定义空调类
20     /// </summary>
21     public class AirConditioner
22     {
23 
24     }
25 
26     /// <summary>
27     /// 直接在房间类中定义性别枚举
28     /// </summary>
29     public enum Sex { man, woman }
30 }

 

posted on 2019-09-20 18:44  yaojieyuan  阅读(607)  评论(0编辑  收藏  举报

导航