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
publicinterface that serves unrelated classes - It has a
protectedinterface 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 ...
随机推荐
- 《高级Web应用程序设计》课程
一.课堂课件 全部授课内容 二.作业 访问ftp://192.168.42.254:22,登录后找到自己的姓名文件夹,放入作业即可.登录账号为stu1,密码为空. 已布置练习 练习1(截止日期10月1 ...
- 解决driver.findElement(By)运行到此处报null指针问题
1.由于自动化页面上的元素定位太多,主要是通过By来定位,而By提供了id,xpath,name差不多就可以定位到元素 可以使用一个配置文件存储页面上的定位By值,然后从配置文件获取by值,行程by方 ...
- 点开看看please
- 实现断点续传的FTP下载类(支持多线程多任务下载)
using System; using System.Collections.Generic; using System.Text; using System.Threading; using Sys ...
- jQuery对象与dom对象的转换
一直以来对于通过jQuery方式获取的对象使不能直接使用JavaScript的一些方法的,开始的时候不理解,现在此案知道,原来jQuery获得的对象并不和我们平时使用getElementById获得的 ...
- Thinkphp 3.2中字符串截取
将此方法放到Thinkphp/Common/function.php里/* * 字符串截取函数 * 大白驴 * 2016-11-29 qq 675835721 * */function msubstr ...
- IIS部署WCF网站服务步骤
一开始在“管理工具”下找不到IIS的快捷方式,是因为系统默认未打开IIS功能,所以首先打开IIS功能: 为避免出现未知的麻烦,建议将IIS下的所有项都勾上: 创建IIS桌面快捷方式: 添加网站托管: ...
- 前端面试题 之 JavaScript
昨天我们一起分享了关于html和css的面试题<前端面试题之Html和CSS>,今天我们来分享关于javascript有关的面试题.我面试的时候最害怕面试官问我js了,因为我真心不擅长这个 ...
- 杭电1597--find the nth digit--假设:S1 = 1,S1=12,S3=123,S4=1234...
我是把它分层来求的,也就是说第一层是1,第二层是12,第三层是123......你们该懂的!! #include <iostream>#include <cmath>using ...
- 更新Mac OSX XCode后Git 不能使用提示Can't start Git: /usr/bin/git
更新Mac OSX XCode后Git 不能使用提示Can't start Git: /usr/bin/git 解决办法: 终端运行 sudo xcodebuild -license 同意协议就好了.