前言

本章节继续讲实现继承。

实现继承

密封类和密封方法

密封类和方法的概念很简单,就是为了不允许类和方法被继承和扩展。不允许扩展一般的原因有:

  • 如果类或者方法被扩展,可能会导致类库执行错误
  • 因为版权原因,不允许第三方随意扩展该类

.Net库有很多密封类,使用者不能随意扩展。我猜测这么做可能是因为设计者想保持框架的纯净性和单一性,即不希望使用者随意扩展而导致出现众多“分支框架”,最终的导致框架的碎片化(参考Andriod的碎片化)。

最典型的,string类型就是密封类。我们可以猜测扩展方法的出现(.Net3.5版本)就是因为对.Net框架密封类有扩展的需求,但是密封类无法继承,所以出一个扩展方法作为“补偿办法”,一定程度上解决了对基础框架的扩展问题。

密封类案例
/// <summary>
/// 密封类案例:不能被继承,其方法不能被override。这个类同时还是基类
/// </summary>
public sealed class SaUser
{
public void Test()
{
//密封类方法不能有virtual关键字,因为virtual代表可override,这和密封类的概念矛盾了
} /// <summary>
/// 此写法为非法,不同通过编译: 基类中不能定义密封方法
/// </summary>
public sealed override void Test2()
{
//Test2()不能定义sealed,也不能定义sealed override,都会导致编译异常。
}
} 密封方法案例
/// <summary>
/// 普通基类
/// </summary>
public class SaUser2
{
public virtual void Test()
{
//可扩展的方法
}
}
/// <summary>
/// 派生类的密封方法
/// </summary>
public class SaUserChilid : SaUser2
{
/// <summary>
/// 密封方法必须是重写的方法
/// </summary>
public sealed override void Test()
{
//密封方法必须同时有sealed和override关键字
base.Test();
}
}

有趣的现象

如上代码,有个有趣的现象是,定义密封类只需要使用sealed关键字,而定义密封方法时,sealed必须和override配对使用。同时,在基类中也不能对方法实行密封。为什么会这样呢?我猜想,设计者的观点应该是:“所谓密封,应该是对一个原先处于“开放”状态下的类进行密封”。但对密封的这个限制,确实使得语言特性不够灵活。实际上,对基类的方法进行密封,虽然极少发生,但理论上还是有需求的。

派生类的构造函数

前面我们讲过了单个类的构造函数。我们知道构造函数是必须的,当我们没有类的构造函数时,系统会默认提供一个构造函数,因为类中字段的数据初始化是依赖于构造函数的。

当我们还要构造较为复杂的派生类时,其构造函数如何运行,就成为一个非常值得研究的问题。研究清楚了它,你才能用“合适”的办法完成派生类的初始化。派生类的构造函数的麻烦,来自于类的“多构造函数”,也就是构造函数的重载。

首先,我们要知道构造函数的原则:

  1. 每个类(基类,派生类)的构造函数都是必须的。
  2. 类的构造是自底向上来构造的,先构造基类,再逐级向上构建派生类。(为什么必须这样逐级构造,可以看原文章了解)
  3. 类的构造方法是可重载的(多构造函数)。

在以上原则下,当一个派生类要开始构造时,我们发现,关键要注意什么?是构造链不能断!在这点上编译器会智能判断,如果它发现构造链断了,会发生编译错误。我们可以看个例子,这个例子我以前的文章就贴过。

/// <summary>
/// 基类
/// </summary>
class Line
{
private int thick; /// <summary>
/// 基类构造方法:代号A
/// </summary>
Line()
{
thick = 1;
}
} /// <summary>
/// 派生类
/// </summary>
public class Rect
{
private int width;
private int height; /// <summary>
/// 构造方法:代号B
/// </summary>
/// <param name="length"></param>
Rect(int length)
:this(length, length) //初始化器
{
//构造一个正方形
} /// <summary>
/// 构造方法:代号C
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
Rect(int width, int height)
:base() //初始化器
{
//构造一个长方形
this.width = width;
this.height = height;
}
}

我给代码中的构造方法都加了代号。以上的demo,我们可以分析得出,如果使用B方法来构造对象,它的构造链是:A->C->B。如果用C方法来构造对象,构造链是:A->C。构造链是清晰的,就没有问题。

修饰符

重申一下何为修饰符:应用于类型或者成员的关键字。

可见性修饰符



不能把类型定义为protected,private,protected interval。嵌套类除外,因为类成员可以使用访问限制性修饰符,而嵌套类是和类的成员同等级的。

其他修饰符

讲完继承,下篇开始讲解接口。

欢迎关注本人微信公众号,更及时的关注最新文章(每周多篇原创文章,以及多篇专题文章):



扫描二维码关注

解读经典《C#高级编程》第七版 Page100-107.继承.Chapter4的更多相关文章

  1. c#高级编程第七版 学习笔记 第一章 .NET体系结构

    第一章      .NET体系结构 本章内容: 编译和运行面向.NET的代码 Microsoft中间语言(Microsoft Intermediate Language,MSIL或简称IL)的优点 值 ...

  2. c#高级编程第七版 学习笔记 第二章 核心c#

    第二章 核心C# 本章内容: 声明变量 变量的初始化和作用域 C#的预定义数据类型 在c#程序中使用条件语句.循环和跳转语句执行流 枚举 名称空间 Main()方法 基本的命令行c#编译器选项 使用S ...

  3. c#高级编程第七版 学习笔记 第三章 对象和类型

    第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...

  4. ASP.NET MVC 4高级编程(第4版)

    <ASP.NET MVC 4高级编程(第4版)> 基本信息 作者: (美)Jon Galloway    Phil Haack    Brad Wilson    K. Scott All ...

  5. 《UNIX环境高级编程(第3版)》

    <UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...

  6. 【转】apue《UNIX环境高级编程第三版》第一章答案详解

    原文网址:http://blog.csdn.net/hubbybob1/article/details/40859835 大家好,从这周开始学习apue<UNIX环境高级编程第三版>,在此 ...

  7. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  8. Unix环境高级编程第三版中实例代码如何在自己的linux上运行的问题

    学习Linux已经有2个月了,最近被期末考试把进度耽误了,前几天把Unix环境高级编程看了两章,感觉对Linux的整体有了一些思路,今天尝试着对第一章涉及到的一个简单的交互式shell编译运行一下,结 ...

  9. C#高级编程 (第六版) 学习 第七章:委托和事件

    第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...

  10. C#高级编程第11版 - 第七章 索引

    [1]7.1 相同类型的多个对象 1.假如你需要处理同一类型的多个对象,你可以使用集合或者数组. 2.如果你想使用不同类型的不同对象,你最好将它们组合成class.struct或者元组. [2]7.2 ...

随机推荐

  1. Flutter 文本样式继承

    使用inherit来设置是否继承样式 DefaultTextStyle( style: TextStyle(color: Colors.red, fontSize: 22), child: Colum ...

  2. vue + websocket 的使用

    阳光正好,我们正在努力前行. 一.引言 初始使用websocket ,一开始看文档的时候,觉得很简单,只需要创建websocket实例,然后有几个监听打开连接,监听关闭连接,监听连接异常等方法.但是, ...

  3. Spring整合MybatisPlus学习笔记

    简介 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生 特性 无侵入:只做增强不做改变,引入它不会对现有 ...

  4. 【转】线段树完全版~by NotOnlySuccess

    线段树完全版  ~by NotOnlySuccess 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时觉得挺自豪的,还去pku打广告,但是现在我自己都不太好意思去看那篇文章了,觉 ...

  5. CSS面试细节整理(二)

    5.css盒模型: CSS 框模型 (Box Model) 规定了元素框处理元素内容.内边距.边框 和 外边距 的方式

  6. CUDA编程模型

    1. 典型的CUDA编程包括五个步骤: 分配GPU内存 从CPU内存中拷贝数据到GPU内存中 调用CUDA内核函数来完成指定的任务 将数据从GPU内存中拷贝回CPU内存中 释放GPU内存 *2. 数据 ...

  7. svn 安装及更新web库

    安装: apt-get update         //更新apt-get库 apt-get install subversion        安装SVN mkdir /home/svn     ...

  8. Kali学习笔记43:SQL盲注

    前面的文章都是基于目标会返回错误信息的情况进行判断是否存在SQL注入 我们可以轻易根据数据库报错信息来猜测SQL语句和注入方式 如果程序员做得比较好,不显示错误信息,这种情况下得SQL注入称为SQL盲 ...

  9. [Swift]LeetCode81. 搜索旋转排序数组 II | Search in Rotated Sorted Array II

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  10. [Swift]LeetCode114. 二叉树展开为链表 | Flatten Binary Tree to Linked List

    Given a binary tree, flatten it to a linked list in-place. For example, given the following tree: 1 ...