C# 图解教程 第5版 —— 第8章 类和继承

8.1 类继承

  • 要派生一个类,需要在类名后面加入 基类规格说明,由冒号和基类名称组成。
  • 派生类不能删除继承的成员。
image-20231026111011929
图8.1 基类规格说明
image-20231026111117403
图8.2 基类和派生类

8.2 访问继承的成员(*)

8.3 所有类都派生自 object 类

​ object 类是唯一的非派生类,是继承层次结构的基础。

image-20231026111341681
图8.3 类层次结构

8.4 屏蔽基类的成员

​ 虽然派生类不能删除继承的成员,但可以声明相同名称的成员来进行屏蔽(覆盖)。屏蔽基类成员的要点如下:

  • 声明一个相同类型、相同名称的成员。
    • 如果屏蔽函数成员,则签名需要相同(签名不包括返回类型)。
  • 使用 new 修饰符告诉编译器在故意屏蔽,否则编译器会发出警告。
  • 也可以屏蔽静态成员。
image-20231026112022389 image-20231026112036517
图8.4 屏蔽基类成员

8.5 基类访问

​ 基类访问表达式由关键字 base 后面跟着一个点和成员的名称组成:

image-20231026112139703
图8.5 基类访问

​ 下面的代码中,使用基类访问表达式访问了被隐藏的 Field1:

image-20231026112253307
图8.5 访问被隐藏的 Field1

​ 一般来说,能够有更优雅的设计避免这种情况,但是实在没办法的时候也可以使用这个特性。

8.6 使用基类的引用

​ 使用类型转换运算符可以将派生类对象的引用转换为基类对象的引用,转换后的引用只能访问基类的成员。

  • 基类的引用“看不到”派生类的其余部分,因为它通过基类类型的引用“看”这个对象。
image-20231026112751219 image-20231026112759875
图8.6 派生类的引用可以看到完整的 MyDerivedClass 对象,而 mybc 只能看到对象的 MyBaseClass 部分

8.6.1 虚方法和覆写方法

​ 上述介绍的内容:使用基类引用访问派生类对象时,得到的是基类成员。

虚方法 可以使基类的引用访问“升至”派生类内。使用基类引用调用派生类的方法条件如下:

  • 派生类方法和基类方法有相同的签名和返回类型。
  • 基类的方法使用 virtual 标注。
  • 派生类的方法使用 override 标注。
image-20231026113203563 image-20231026113217159 image-20231026113259442
图8.7 虚方法和覆写方法

​ 关于 virtual 和 override 的重要信息如下:

  • 覆写和被覆写的方法必须有相同的可访问性。
  • 不能覆写 static 方法或非虚方法。
  • 方法、属性、索引器、事件都可以被声明为 virtual 和 override。

8.6.2 覆写标记为 override 的方法

​ 覆写方法可以在继承的任何层次出现。使用基类部分的引用调用一个被覆写的方法时:

  1. 方法调用沿派生层次上溯执行,直到标记为 override 方法的最高派生版本。
  2. 如果有更高派生级别的方法但没有标记为 override,则不会被调用。
image-20231026113814694
图8.8 具有派生层次的三个类

情况1:使用 override 声明 Print

image-20231026113958997 image-20231026114009930
图8.9 override 声明 Print 及输出结果

​ 结果说明:无论是通过派生类还是通过基类引用调用,都会调用最高派生类中的方法。

image-20231026114037205
图8.10 执行被传递到多层覆写链的顶端

情况2:使用 new 声明 Print

image-20231026114350210 image-20231026114414493
图8.11 new 声明 Print 及输出结果

​ 结果说明:方法调用只向上传递了一级,因为最高层的方法没有被声明为 override。

image-20231026114426173
图8.12 隐藏覆写的方法

8.6.3 覆盖其他类型成员(*)

8.7 构造函数的执行

  • 要创建对象的基类部分,需要隐式调用基类的某个构造函数。
  • 继承层次链中的每个类在执行自己的构造函数体之前执行它的基类构造函数。
class MyDerivedClass : MyBaseClass
{
    MyDerivedClass() { // 构造函数调用基类构造函数 MyBaseClass()
        ...
    }
}
image-20231026114936221
图8.13 对象构造的顺序

​ 强烈反对在构造函数中调用虚方法。

8.7.1 构造函数初始化语句

  • 第一种形式:使用关键字 base 指明使用哪一个基类构造函数。
image-20231026115315583
图8.14 第一种形式初始化语句

​ 当声明一个不带构造函数初始化语句的构造函数时,实际上是带有 base() 构造函数初始化语句的简写形式:

image-20231026115451437
图8.15 等价的构造函数形式
  • 第二种形式:使用关键字 this 指明使用当前类的哪一个构造函数。
image-20231026115557173
图8.16 第二种形式初始化语句

​ 当类需要多个构造函数时:

  • 推荐做法:提取公共代码至一个构造函数内,其他构造函数使用该公共构造函数进行初始化。

  • 不推荐做法:提取公共代码至一个方法内,让所有构造函数调用这个方法。

    原因:

    • 编译器对构造函数能有一些特殊优化。
    • 有些事情必须在构造函数中进行,例如初始化 readonly 字段。

8.7.2 类访问修饰符

​ 类的可访问性只有两个级别:

  1. public:能够被系统内任何程序集中的代码访问。

  2. internal:只能被自己所在程序集(不是程序,也不是 DLL)中的类看到。

​ 默认访问级别是 internal。

image-20231026120324534
图8.17 其他程序集中的类可以访问公有类但不能访问内部类

8.8 程序集间的继承

​ C# 允许在不同的程序集之间进行继承。要从其他程序集中的基类派生类,句许具备如下条件:

  1. 基类被声明为 public 以供外部访问。
  2. 添加对程序集的引用以找到基类。
    • 增加对程序集的引用并不是使用 using 指令,而是告诉编译器所需的类型在哪里定义。
    • using 指令是允许引用其他的类而不必使用它们的完全限定名称。
image-20231026145046102
图8.18 Assembly1.cs
image-20231026145220559 image-20231026145157532
图8.19 Assembly2.cs
image-20231026145327305
图8.20 跨程序集继承

8.9 成员访问修饰符

  • 所有显示声明在类中的成员都是相互可见的,无论它们的访问性如何。即,同一类中的成员是相互透明的。
  • 继承的成员不在类中显示声明,因此对派生类不一定可见。
  • 成员的隐式访问级别为 private,一共有 5 中可访问级别:
    • public
    • private
    • protected
    • internal
    • protected internal
  • 成员的可访问性不能比类高。

8.9.1 访问成员的区域

​ 如下所示,MyClass 被声明为 public,因此所有程序集都可以访问该类,但其成员是否可访问依赖于成员的访问修饰符:

image-20231026150324683 image-20231026150313814
图8.21 访问性的区域划分

​ 另一个类能否访问 MyClass 的成员取决于该类的以下两个特征:

  1. 是否派生自 MyClass。
  2. 是否和 MyClass 在同一程序集。

​ 依据这两个特征可以划分出图 8.21 中的 4 个区域。

8.9.2 公有成员的可访问性

​ public 访问级别的限制是最少的(几乎没有的),所有类都可以自由访问该成员。

image-20231026150654828
图8.22 公有类的公有成员对同一程序集或其他程序集的所有类可见

8.9.3 私有成员的可访问性

​ private 访问级别的限制是最严格的,只有自己或嵌套在自己内部的类才能访问类成员,其他所有类都不行。

image-20231026150822749
图8.23 任何类的私有成员只对它自己的类(或嵌套类)的成员可见

8.9.4 受保护成员的可访问性

​ 比 private 限制稍宽松,在 private 的基础上还允许子类访问。

image-20231026151032794
图8.24 公有类的受保护成员对它自己的类成员或派生类的成员可见,派生类甚至可以在其他程序集中

8.9.5 内部成员的可访问性

​ internal 允许成员对程序集内部的所有类可见,对程序集外部的所有类不可见。

image-20231026151208350
图8.25 内部成员对同一程序集内部的任何类成员可见,但对程序集外部的类不可见

8.9.6 受保护内部成员的可访问性

​ protected internal 的访问性是 protected 和 internal 的 并集,不是交集。

image-20231026151405084
图8.26 公有类的受保护内部成员对相同程序集的类成员或继承该类的类成员可见,对其他程序集中且不继承该类的类不可见

8.9.7 成员访问修饰符小结

表8.1 成员访问修饰符
image-20231026151528212

​ 图 8.27 演示了成员访问修饰符的可访问级别。

image-20231026151630946
图8.27 各种成员访问修饰符的相对可访问性

​ 表 8.2 总结了以上所有情况。

表8.2 成员可访问性总结
image-20231026151738219

8.10 抽象成员

​ 抽象成员是待被覆写的函数成员,具有如下特征:

  • 必须是函数成员。
  • 必须用 abstract 修饰符标记。
  • 不能有实现代码块,而用分号代替。
image-20231026190311331
图8.28 抽象成员的声明

​ 以下类型的成员可以被声明为抽象成员:

  • 方法。
  • 属性。
  • 事件。
  • 索引器。

​ 其他重要事项如下:

  1. 不能将 virtual 修饰符附加到抽象成员上。
  2. 类似于虚成员,派生类中抽象成员的实现必须指定 override 修饰符。
表8.3 比较虚成员和抽象成员
image-20231026190544687

8.11 抽象类

​ 抽象类只能被用作其他类的基类。

  • 不能创建抽象类的实例。
  • 抽象类使用 abstract 修饰符声明。
  • 抽象类可以包含抽象成员或非抽象成员。
  • 抽象类自己可以派生自另一个抽象类。
  • 任何派生自抽象类的类必须使用 override 关键字实现该类所有的抽象成员,除非自己也是抽象类。
image-20231026190825211
图8.29 抽象类的声明

8.11.1 抽象类和抽象方法的示例(*)

8.11.2 抽象类的另一个例子(*)

8.12 密封类

  • 密封类只能被用作独立的类,不能被用作基类。
  • 使用 sealed 修饰符标注。
image-20231026191009984
图8.30 密封类的声明

8.13 静态类

​ 静态类的一个常见用途是创建一个包含一组数学方法和值的数学库。

  • 类本身必须标记为 static。
  • 所有成员必须是 static。
  • 可以有一个静态构造函数,但不能有实例构造函数。
  • 静态类隐式密封。
image-20231026191154082 image-20231026191206089
图8.31 静态类示例

​ C# 6.0后,可以使用 using static 指令访问静态类的成员,而不必使用类名。

8.14 扩展方法

​ 几乎整个 LINQ 库都是通过扩展方法来实现的。

  • 声明扩展方法的类必须声明为 static。
  • 扩展方法本身必须声明为 static。
  • 扩展方法必须包含关键字 this 作为第一个参数类型,后面跟着拓展类的名称。
image-20231026191619861 image-20231026191633334
图8.32 扩展方法的声明和结构

8.15 命名约定

表8.4 常用的标识符命名风格
image-20231026192028687

​ 说明:下划线不常出现在标识符的中间位置。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《C How to Program,Fifth Edition》(中文名:《C大学教程》),作者:【美】P.J.Deitel、【美】H.M.Deitel,翻译:苏小红、李东、王甜甜,出社:电子工业出社,ISBN:978-7-121-05662-8,PDF 格式,大小 352 Mb,被压缩为 7 部分,本资源是第一部分;第一部分下载地址:http://download.csdn.net/source/3289551;第二部分下载地址:http://download.csdn.net/source/3286123;第三部分下载地址:http://download.csdn.net/source/3285981;第四部分下载地址:http://download.csdn.net/source/3284551;第五部分下载地址:http://download.csdn.net/source/3283848;第六部分下载地址:http://download.csdn.net/source/3290125;第七部分下载地址:http://download.csdn.net/source/3280289。 七个资源在一起解压缩后(windows 平台下解压缩)即可得到《C大学教程(第五·中文)》.pdf 一书。 内容简介: 本书是全球最畅销的C语言教程之一。本书系统地介绍了四种当今流行的程序设计方法——面向过程、基于对象、面向对象以及泛型编程,内容全面、生动、易懂,作者由浅入深地介绍结构化编程及软件工程的基本概念,从简单的概念到最终完整的语言描述,清晰、准确、透彻、详细地讲解C语言,尤其注重程序设计思想和方法的介绍。相对于以往的本,在内容方面,本书新增加了介绍C99标准、排序、基于Allegro C函数库的游戏编程以及有关C++面向对象程序设计的节,并且在附录中增加了Sudoku游戏程序设计的讲解。新加入的“活代码”方法(即通过可执行的代码来讲解理论概念的方法)是本书的另一特色,它可以促进学生积极地参与到程序设计中来。突出显示的各种程序设计提示,则是作者多年教学经验的总结。 本书不仅适合于初学者学习,作为高校计算机程序设计教学的教科书,也同样适用于有经验的程序员,作为软件开发人员的专业参考书。 内容预览: 第1 计算机、Internet和万维网导论 第2 C语言程序设计入门 第3 结构化的C程序设计 第4 C程序控制 第5 C函数 第6 C数组 第7 C指针 第8 C字符和字符串 第9 格式化输入输出 第10 结构体、共用体、位操作和枚举型 第11 文字处理 第12 数据结构 第13 C预处理 第14 C语言的其他专题 第15 基于Allegro C函数库的游戏编程 第16 排序:更深入的透视 第17 C99简介 第18 C++,一个更好的C;介绍对象技术 第19 与对象简介 第20 ;深入剖析(第1部分) 第21 ;深入剖析(第2部分) 第22 运算符重载 第23 面向对象编辑:继承 第24 面向对象编程:多态 第25 模板 第26 输入/输出 第27 异常处理 附录A 因特网和Web资源、 附录B 运算符优先级表、 附录C ASCLL字符集 附录D 数制系统 附录E 游戏编程:求解Sudoku问题 索引

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔗理苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值