第十九条:要么为继承而设计并提供文档说明,要么就禁止继承

在前面一条中,我们已经知道了David写了A类被Tom拿去继承了,导致了A类的封装性遭到了破坏,那么有没有可能做点事情避免此事发生呢?第十九条孕育而生!David在创建A类的时候写上文档说明,说Al类不允许任何类来继承,Tom看到后就不会这么做了,除非Tom喜欢写狮山代码,一上来不看别人别的文档说明,一上来就操作猛如虎(这类人现实中其实挺多的)。

好的API应该描述一个给定的方法做了什么工作,而不是描述他是如何做到的。

那么,当你为了继承而设计的类的时候,如何决定应该暴露那些受保护的成员呢?遗憾的是,并没有神奇的法则可供你使用。唯一的方法就是测试。

要测试一个为继承而设计的类,唯一的测试方法就是编写子类。经验表明,3个子类通常就足可以测试一个可扩展的类。

当设计一个可能被广泛使用的用于继承的类时,要意识到,我们对写在文档中的方法的自身使用情况,以及隐含在受保护的方法和字段的实现决策做出了永久性的承诺。这些承诺可能会使在随后的版本中改进这个类的性能或功能变得困难,甚至不可能。因此,在发布之前必须通过编写子类来测试。

还有些允许继承的类必须遵守的限制。构造器不得直接或者间接调用可重写的方法。违反这个规定,有可能导致程序失败。超类的构造器会在子类的构造器之前运行,所以子类重写的方法会在子类构造器之前被调用。

例子:

public class Super{//存在问题 构造器调用了一个可重写的方法public Super() {overrideMe();}public void overrideMe(){}
}
public final class Sub extends Super{// 一个空的final字段,由构造器设置private final Date date;public Sub(){date=new Date();}//超类构造器调用的重写方法@Overridepublic void overrideMe(){System.out.println(date);}public static void main(String[] args){Sub sub=new Sub();sub.overrideMe();}
}

结果:

Connected to the target VM, address: '127.0.0.1:51415', transport: 'socket'
null
Wed Jun 26 21:52:51 CST 2024
Disconnected from the target VM, address: '127.0.0.1:51415', transport: 'socket'Process finished with exit code 0

你可能会期待这个程序会打印出日期俩次,但是它第一次打印出的是null,因为overrideMe方法被Super构造器调用的时候,构造器Sub还没有机会初始化Date域

在为了继承而设计的类的时候,Cloneable和Serializable接口出现了特殊的困难。如果类是为了继承而被设计的,无论实现这其中的那个接口通常都不是一个好主意,因为他们它一下实质性的负担转嫁到扩展这个类的程序员的身上。

如果你决定在一个为了继承而设计的类中实现Cloneable或者Serializable接口,就应该意识到,因为clone和readObject方法在行为上非常类似于构造器,所以类似的限制规则也是使用的:无论是clone还是readObject,都不可以调用可覆盖的方法,不管是以直接还是间接的方式。

如果你决定在一个为了继承而设计的类中实现Serializable,并且该类有一个readResolve或者writeReplace方法,就必须使readResolve或者writeReplace成为受保护的方法,而不是私有的方法。

现在我们很清楚了,设计一个用于继承的类需要付出巨大的努力,对类本身也是很大的限制。

解决这个问题的最佳方案是,对于并非为可以安全地子类化而设计并提供文档说明的类,禁止对其子类化。

所有文章无条件开放,顺手点个赞不为过吧!

                       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/35829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

node 实现导出, 在导出excel中包含图片(附件)

如果想查看 node mySql 实现数据的导入导出,以及导入批量插入的sql语句,连接如下 node mySql 实现数据的导入导出,以及导入批量插入的sql语句-CSDN博客https://blog.csdn.net/snows_l/article/details/139998373 一、效果如图: 二…

中介子方程三十四

XXFXXuXXWXXuXXdXXrXXαXXuXpXXKXηXiXXαXXiXηXKXXpXuXXαXXrXXdXXuXWXπXXWXeXyXeXbXπXpXXNXXqXeXXrXXαXXuXpXXKXηXiXXαXXiXηXKXXpXuXXαXXrXXeXqXXNXXpXπXbXeXyXeXWXXπXWXuXXdXXrXXαXXuXpXXKXηXiXXαXXiXηXKXXpXuXXαXXrXXdXXuXXWXXuXXFXXEXXyXXEXXrXXαXXuXpXXK…

paraview跨节点并行渲染

参考: https://cloud.tencent.com/developer/ask/sof/101483588 ParaView 支持使用其内置的网络拓扑来进行跨节点的并行渲染。以下是一个简单的步骤来设置和运行跨节点的并行渲染: 确保你的计算环境支持多节点计算,比如通过SSH、MPI或其他集…

阿里云扩容

官网:https://help.aliyun.com/zh/ecs/user-guide/extend-the-partitions-and-file-systems-of-disks-on-a-linux-instance?spm5176.ecs-console-storage_disk.help.dexternal.72d24df5QOL4ss 博客:http://t.csdnimg.cn/cUykr

Android APP通过View修改鼠标样式

app view上修改鼠标样式比较简单,使用如下方法修改为自定义图片: getWindow().getDecorView().setPointerIcon(PointerIcon.load(getResources(), R.drawable.pointer_spot_touch_icon)); 设置鼠标样式setPointerIcon的调用栈 frameworks/base/core/jav…

C语言:流量控制

前言 流量控制可以让发送端根据接收端的实际接受能力控制发送的数据量。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不会超过该大小的数据,该限制大小即为窗口大小,即窗口大小由接收端主…

【Linux详解】进程的状态 | 运行 阻塞 挂起 | 僵尸和孤儿状态

目录 操作系统中 运行状态 阻塞状态 进程状态转换 Linux系统中 查看进程状态 深度睡眠状态 T 暂停状态 Z 僵尸状态 孤儿状态 文章手稿 xmind: 引言 介绍系统中的进程状态及其管理方式。将通过结合操作系统原理和实际代码示例,详细说明进程的各种状态、转换…

鸿蒙开发Ability Kit(程序框架服务):【FA模型切换Stage模型指导】 app和deviceConfig的切换

app和deviceConfig的切换 为了便于开发者维护应用级别的属性配置,Stage模型将config.json中的app和deviceConfig标签提取到了app.json5中进行配置,并对部分标签名称进行了修改,具体差异见下表。 表1 配置文件app标签差异对比 配置项FA模型…

Excel中的“点选输入”——次级下拉列表创建

在Excel中,用“数据验证”功能可以设置下拉列表,二级下拉列表需要设置公式。 (笔记模板由python脚本于2024年06月16日 18:36:37创建,本篇笔记适合经常使用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:http…

基于 Spring AOP 实现安全检查

在现代应用程序中,安全性是一个至关重要的方面。通过对系统中的关键操作进行安全检查,可以有效防止未授权的访问和操作。Spring AOP(面向切面编程)提供了一种优雅的方式来实现安全检查,而无需修改业务逻辑代码。本文将…

后端之路第三站(Mybatis)——入门配置

一、Mybatis是啥? 就是一个用java来操控数据库的框架语言 之前学的datagrip或者navicat这些软件里我们操作数据库,原理是我们编写完的操作语句发送到服务器传送到数据库系统,然后数据库执行完之后再发送给服务器返回给datagrip或者navicat显…

【linux/shell案例实战】shell界面命令快捷键

快捷键及含义: Ctrl+u剪切光标之前的内容。Ctul+k剪切光标之后的内容。Ctrl+e让光标移动到命令最前,Ctrl+a让光标移动到命令最后Ctrl+y 粘贴刚才所删除的内容。Ctrl+d 删除光标所在…

GPT-5:AI的博士时代与我们的未来

目录 引言第一部分:GPT-5技术突破预测1. NLP技术的革新1.1 算法进步对理解力提升的影响1.2 技术突破推动行业发展 2. 行业推动力2.1 教育行业的变革2.2 医疗行业的创新2.3 法律行业的效率提升 第二部分:智能系统与人类的协作1. 辅助决策的角色1.1 决策支…

游戏AI的创造思路-技术基础-sigmoid函数详解

在前面的机器学习和深度学习的内容中,大量出现了sigmoid函数,所以本篇为大家介绍下sigmoid函数,希望对大家理解前面的算法和后面的Transformer有所帮助 目录 3.8. sigmoid函数 3.8.1. 定义 3.8.2. 性质 3.8.3. 应用 3.8.4. 缺点 3.8.5.…

Flutter实现页面间传参

带参跳转 步骤 在router中配置这个路由需要携带的参数,这里的参数是 arguments,注意要用花括号包裹参数名称 在相应组件中实现带参构造函数 在state类中可以直接使用${widget.arguments}来访问到传递的参数 在其他页面中使用Navigator.pushNamed()带参跳转

【昇思初学入门】第八天打卡-模型保存与加载

模型保存与加载 学习心得 保存 CheckPoint 格式文件,在模型训练过程中,可以添加检查点(CheckPoint)用于保存模型的参数,以便进行推理及再训练使用。如果想继续在不同硬件平台上做推理,可通过网络和CheckPoint格式文件生成对应的…

C++中常用的标志库

标准库 C标准库是一个强大的工具集&#xff0c;它包含了一组丰富的类和函数&#xff0c;可以帮助开发者进行各种操作&#xff0c;如输入输出、字符串操作、数据结构管理、算法实现等。以下是一些常用的C标准库及其使用方法。 1. 输入输出库 <iostream> 用于标准输入输…

2024年最新通信安全员考试题库

61.架设架空光缆&#xff0c;可使用吊板作业的情况是&#xff08;&#xff09;。 A.在2.2/7规格的电杆与墙壁之间的吊线上&#xff0c;吊线高度5m B.在2.2/7规格的墙壁与墙壁之间的吊线上&#xff0c;吊线高度6m C.在2.2/7规格的电杆与电杆之间的吊线上&#xff0c;吊线高度…

[leetcode]24-game

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:static constexpr int TARGET 24;static constexpr double EPSILON 1e-6;static constexpr int ADD 0, MULTIPLY 1, SUBTRACT 2, DIVIDE 3;bool judgePoint24(vector<int> &nums) {vector&l…

【C++LeetCode】【热题100】三数之和【中等】-不同效率的题解【6】

题目&#xff1a; 暴力方法&#xff1a; class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> res;std::unordered_set<std::string> uniqueValues;//保证结果唯一for(int i0;i<n…