How can I protect derived classes from breaking when I change the internal parts of the base class?
How can I protect derived classes from breaking when I change the internal parts of the base class?
A class has two distinct interfaces for two distinct sets of clients:
- It has a
public
interface that serves unrelated classes - It has a
protected
interface that serves derived classes
Unless you expect all your derived classes to be built by your own team, you should declare your base class’s data members as private
and use protected
inline
access functions by which derived classes will access the private
data in the base class. This way the private
data declarations can change, but the derived class’s code won’t break (unless you change the protected
access functions).
I’ve been told to never use protected data, and instead to always use private data with protected access functions. Is that a good rule?
Nope.
Whenever someone says to you, “You should always make data private,” stop right there — it’s an “always” or “never” rule, and those rules are what I call one-size-fits-all rules. The real world isn’t that simple.
Here’s the way I say it: if I expect derived classes, I should ask this question: who will create them? If the people who will create them will be outside your team, or if there are a huge number of derived classes, then and only then is it worth creating a protected interface and using private data. If I expect the derived classes to be created by my own team and to be reasonable in number, it’s just not worth the trouble: use protected data. And hold your head up, don’t be ashamed: it’s the right thing to do!
The benefit of protected access functions is that you won’t break your derived classes as often as you would if your data was protected. Put it this way: if you believe your users will be outside your team, you should do a lot more than just provide get/set methods for your private data. You should actually create another interface. You have a public interface for one set of users, and a protected interface for another set of users. But they both need an interface that is carefully designed — designed for stability, usability, performance, etc. And at the end of the day, the real benefit of privatizing your data (including providing an interface that is coherent and, as much as possible, opaque) is to avoid breaking your derived classes when you change that data structure.
But if your own team is creating the derived classes, and there are a reasonably small number of them, it’s simply not worth the effort: use protected data. Some purists (translation: people who’ve never stepped foot in the real world, people who’ve spent their entire lives in an ivory tower, people who don’t understand words like “customer” or “schedule” or “deadline” or “ROI”) think that everything ought to be reusable and everything ought to have a clean, easy to use interface. Those kinds of people are dangerous: they often make your project late, since they make everything equally important. They’re basically saying, “We have 100 tasks, and I have carefully prioritized them: they are all priority 1.” They make the notion of priority meaningless.
You simply will not have enough time to make life easy for everyone, so the very best you can do is make life easy for a subset of the world. Prioritize. Select the people that matter most and spend time making stable interfaces for them. You may not like this, but everyone is not created equal; some people actually do matter more than others. We have a word for those important people. We call them “customers.”
这里可以看出protected member同样属于一种接口协定,是面向继承者的接口,相对而言也要保持稳定, 所以一个通用的建议就是:成员变量定义成private,提供protected访问接口函数。
但是如果继承只是发生在类库的内部,而且规模较小,有时候直接定义protected成员变量也是可以的,而且更方便。
How can I protect derived classes from breaking when I change the internal parts of the base class?的更多相关文章
- 【转载】#330 - Derived Classes Do Not Inherit Constructors
A derived class inherits all of the members of a base class except for its constructors. You must de ...
- [C++] OOP - Base and Derived Classes
There is a base class at the root of the hierarchy, from which the other class inherit, directly or ...
- Virtual functions in derived classes
In C++, once a member function is declared as a virtual function in a base class, it becomes virtual ...
- Effective C++ 之 Item 5:了解C++默默编写并调用哪些函数
Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 5 ...
- C++编译器默默编写并调用哪些函数
什么时候empty class(空类)不再是个empty class呢?当C++处理过它之后,是的,如果你自己没有声明,编译器就会为它声明(编译器版本)一个copy构造函数.一个copy assign ...
- EC读书笔记系列之3:条款5、条款6、条款7
条款5:了解C++默默编写并调用哪些函数 记住: ★编译器可以(仅仅是可以,并非必须,仅当程序中有这样的用法时才会这么做!!!)暗自为class创建default构造函数,copy构造函数,copy ...
- EffectiveC++ 第6章 继承与面向对象设计
我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 6 继承与面向对象设计 Inheritance and ...
- [转]Entity Framework Fluent API - Configuring and Mapping Properties and Types
本文转自:https://msdn.microsoft.com/en-us/data/jj591617#1.2 When working with Entity Framework Code Firs ...
- <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<二>
<Item 9> Never call virtual functions during construction or destruction 1.you shouldn't call ...
随机推荐
- node.js基础 1之 Querystring参数处理小利器
在处理查询字符串中很有用(⊙o⊙)哦~~~ querystring.stringify(obj,sign1,sign2)//将对象转化成url中query部分的形式 参数:1.要转化的对象 2.链接符 ...
- 解决eclipse之ADT与SDK版本不一致问题
This Android SDK requires Android Developer Toolkit version … .Please update ADT to the latest versi ...
- (48) odoo的button用法
button 应用的比较多,这里来汇总一下 按钮<button>,支持的属性 icon 可用的icon在 addons/web/static/src/img/icons ...
- 改变CSS世界纵横规则的writing-mode属性
改变CSS世界纵横规则的writing-mode属性 这篇文章发布于 2016年04月27日,星期三,23:12,归类于 css相关. 阅读 8292 次, 今日 71 次 by zhangxinxu ...
- NAND flash sub-pages
http://www.linux-mtd.infradead.org/doc/ubi.html#L_subpage NAND flash sub-pages As it is said here, a ...
- js面向对象的使用方法
标准用法: function Sprite(){ //函数内容部设置属性 this.name='shimily'; } //原型上设置方法 Sprite.prototype.show=function ...
- span 元素无法设置宽度问题
span 元素为行内元素,没有width属性,需要转换为块级元素才可以设置width: 拓展:html元素分为块级元素,行内元素.可变元素. 行内元素与块级元素直观上的区别 1 .行内元素会在一条直线 ...
- [教训] windows 电脑的垃圾文件清理...
坑你没商量! 这个名叫 “清除系统垃圾.bat“ 的文件在网上传播很广,但是,却出现了错误的版本,如果按照它逐条执行,将导致系统文件夹被一锅端,只能再重装的悲剧! 举个栗子: 错误版本:http:// ...
- config配置文件的一些东西
/* 模板相关配置 */ 'TMPL_PARSE_STRING' => array( '__STATIC__' => __ROOT__ . '/Public/static', '__ADD ...
- Imagick 缩放图片和实现模糊
Imagick功能相当的多,只是还不稳定,我下面的程序能够运行,但是会出现内存错误,但我们要的图片还是能够得到. 弄这个的原因是,一个客户要求在一个appcan的应用里面实现一个页面的背景图的缩放.调 ...