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?的更多相关文章

  1. 【转载】#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 ...

  2. [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 ...

  3. Virtual functions in derived classes

    In C++, once a member function is declared as a virtual function in a base class, it becomes virtual ...

  4. Effective C++ 之 Item 5:了解C++默默编写并调用哪些函数

    Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 5 ...

  5. C++编译器默默编写并调用哪些函数

    什么时候empty class(空类)不再是个empty class呢?当C++处理过它之后,是的,如果你自己没有声明,编译器就会为它声明(编译器版本)一个copy构造函数.一个copy assign ...

  6. EC读书笔记系列之3:条款5、条款6、条款7

    条款5:了解C++默默编写并调用哪些函数 记住: ★编译器可以(仅仅是可以,并非必须,仅当程序中有这样的用法时才会这么做!!!)暗自为class创建default构造函数,copy构造函数,copy ...

  7. EffectiveC++ 第6章 继承与面向对象设计

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 6 继承与面向对象设计 Inheritance and ...

  8. [转]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 ...

  9. <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<二>

    <Item 9> Never call virtual functions during construction or destruction 1.you shouldn't call ...

随机推荐

  1. Android开发之无线遥控器

    最近弄了一个UDP/TCP的小东西,主要需要实现的功能如下(服务器端): 1.基于局域网 2.服务器端网络接口为无线与有线 3.服务器端接收到客户端的数据需要模拟按键进行处理 4.开机自启动 5.使用 ...

  2. cookie的弊端

    cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的. 第一:每个特定的域名下最多生成20个cookie   1.IE6或更低版本最多20个cookie 2.I ...

  3. Phalapi 中Union和Union All的用法

    有时候在进行数据库查询的时候会用到union查询,但是查询的时候会发现两个limit只有一个是有效的,如下查询 select * from table where status = 0 limit 1 ...

  4. IIS发布网站出现“未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项。”的解决方法

    未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序.              说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈 ...

  5. SSM框架学习之高并发秒杀业务--笔记5-- 并发优化

    前几节终于实现了这个高并发秒杀业务,现在问题是如何优化这个业务使其能扛住一定程度的并发量. 一. 优化分析 对于整个业务来说,首先是分析哪些地方会出现高并发,以及哪些地方会影响到了业务的性能.可能会出 ...

  6. 【转】Spring bean处理——回调函数

    Spring bean处理——回调函数 Spring中定义了三个可以用来对Spring bean或生成bean的BeanFactory进行处理的接口,InitializingBean.BeanPost ...

  7. AutoCAD学习笔记

    学习笔记: **有些命令,有两到三种执行方式:菜单.命令行.对话框.如layer命令,如果在命令行打入layer命令,就会弹出对话框主y式,如果要命令行方式执行,就需要在前面加一个-号,即-layer ...

  8. hello 漂亮的小靓仔

    <form type="text" name="超级" method="post"> <table align=" ...

  9. Firebug的下载安装

    网上下载到的Firebug最后得到的都是一个.xpi文件 这个文件直接从文件夹拖入火狐浏览器就可以完成安装了,但浏览器总会告诉你无法通过验证.... 这时候你只需要在火狐浏览器中输入about:con ...

  10. The connection to adb is down, and a severe error has occured.问题解决方法小结

    遇到了几次这个问题:The connection to adb is down, and a severe error has occured. You must restart adb and Ec ...