刚开始接触OOP的时候,打心底里我不喜欢private与protected。我声明一个public然后不直接用它,不就跟private一样吗?在某些场合下,我还能偷偷地用一下public变量,这不是更方便吗?所以,以前写的class,除了class几个字母外,其它的跟struct没啥区别。做了几个小项目之后,我终于浪子回头。下面进入今天的正题——爱上private吧。

理由1。。。

假如一个member value不是public,唯一能够访问它的就是friend和API。我想,没有人会希望在写程序的时候喜欢因考虑是否需要()而浪费时间。所以,将member value声明为private,直观上能帮助我们减少这方面搔首挠耳的时间。比如,下面的这个例子,

class AccessLevels
{
public:
int getReadOnly();
int setReadOnly();
int setWriteOnly();
...
private:
int readOnly;
int writeOnly;
...
};

使用的时候,我们会毫不犹豫地加上()。还不止这些,假如你将member value设置为public,有一天你头晕晕地在A脚本中对readOnly修改为0,然后再B脚本百思不得其解的时候,你就会发现private在保护你的menber value时起到的作用了。

理由2。。。

也许,上面的例子还不足以让你信服,就像当初我刚学OOP时抵触private一般。下面我们换个高级一点的角度来看待这个问题:封装。再来一个简单的例子.

class SpeedDataCollection
{
public:
void addValue(int speed); //添加新的数据
double averageSoFar() const; //返回平均速度
};

averageSoFar()的实现方式有两种,一种是添加一个成员变量,记录到现在为止所有速度的平均值。一种是调用的时候,收集所有速度值,然后再求平均值。

第一种方法会让SpeedDataCollection对象变大,多出的空间用于存放目前的平均值,累积总量,数据数量。但是averageSoFar十分高效。第二种方法不用记录很多内容,但是每次都需要计算,执行比较慢。

试想一下,在一台路边的测速装置上,能有多少内存能够使用。并且也不是每时每刻都需要平均速度,对于这种仪器,使用第一种方法比较合适。而假如我们要在屏幕上面显示当前赛车的平均速度,对于averageSoFar的性能要求就会非常高,所以采用第二种方式比较合适。而客户使用averageSoFar的时候,只会知道效果不错,但是却不用关心背后的实现方式。这就是使用private变量,也就是封装带来的好处,将member隐藏在接口后面,让所有可能的实现变得有弹性。

理由3。。。

最近在使用Unity3D开发游戏,虽然使用的是C#,但是由于使用了过多的public变量让人的确非常头痛。比如,NPC的状态使用一个state变量进行标记,在跑道上,NPC的状态千变万化,也就是在客户的代码上,不断地修改着NPC的状态。比如,使用了一个保护罩,在保护的时间再使用一个保护罩,每个保护罩在消失的时候就会将state从保护状态更改为非保护状态。那么第一个保护罩消失的时候发生了什么事呢?第二个保护罩还在,但是状态已经是非保护状态了。这个时候就非常头疼了,因为使用到state的客户端代码非常多,很难在茫茫人海中找到那个它(bug)。

假如state为private,那么访问它的只有SetState()与GetState(),那么当程序出问题的时候,我或许只需要关注这两个函数的实现方式即可。这多么让人惊讶!!!一开始使用public是为了方便,最后却发现private提供了更多的便利!!!

再举个栗子,我们在程序的后期取消了public ... state变量,那么有多少代码会受到影响呢?那往往是一个不可知的大量。

最后,为什么说使用private而不使用protected呢?##

客户是有相对的,比如,主函数中的代码可以是类的客户,而派生类也可以是客户。假如我们使用了protected,意味着在derived class中可以随心所欲地修改base class中的protected成员。把理由3照搬到这里来依然成立。由此可以看出,当存在继承的时候,base class中的protected与public同样不具备封装性。

为了更好更方便地活着——爱上private的更多相关文章

  1. Dnsmasq安装与配置-搭建本地DNS服务器 更干净更快无广告DNS解析

    默认的情况下,我们平时上网用的本地DNS服务器都是使用电信或者联通的,但是这样也导致了不少的问题,首当其冲的就是上网时经常莫名地弹出广告,或者莫名的流量被消耗掉导致网速变慢.其次是部分网站域名不能正常 ...

  2. 采用ADM2483磁隔离器让RS485接口更简单更安全

    采用ADM2483磁隔离器让RS485接口更简单更安全 摘要:本文介绍RS485的特点及应用,指出了普通RS485接口易损坏的问题,针对存在的问题介绍了以ADM2483为核心的磁隔离解决方案. 关键词 ...

  3. 正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)

    source: https://swtch.com/~rsc/regexp/regexp1.html translated by trav, travmymail@gmail.com 引言 下图是两种 ...

  4. 金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(实战篇)

    本文作者:丁同舟,来自金蝶随手记技术团队. 1.前言 本文接上篇<金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)>,以iOS端的Objective-C代 ...

  5. 更轻更快的Vue.js 2.0与其他框架对比(转)

    更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0  ...

  6. EpiiServer 更快捷更方便的php+nginx环境定制化方案

    EpiiServer是什么 更快捷更方便的php+nginx多应用部署环境. github仓库首页 https://github.com/epaii/epii-server gitee仓库 https ...

  7. 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转

    线程安全使用(四)   这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...

  8. Mockplus更快更简单的原型设计

    更快更简单的原型设计 https://www.mockplus.cn/ Mockplus,更快更简单的原型设计工具.快速创建原型,一键拖拽创建交互,团队协作省事省力.微软.华为.东软.育碧.Oracl ...

  9. Google 开源的依赖注入库,比 Spring 更小更快!

    Google开源的一个依赖注入类库Guice,相比于Spring IoC来说更小更快.Elasticsearch大量使用了Guice,本文简单的介绍下Guice的基本概念和使用方式. 学习目标 概述: ...

随机推荐

  1. No module named pip.req

    https://stackoverflow.com/questions/25192794/no-module-named-pip-req#

  2. Nmap介绍

    1.Nmap介绍 Nmap用于列举网络主机清单.管理服务升级调度.监控主机或服务运行状况.Nmap可以检测目标机是否在线.端口开放情况.侦测运行的服务类型及版本信息.侦测操作系统与设备类型等信息. 1 ...

  3. CEO 是一家创业公司的天花板

    大家说是不是呢?一秒钟内看到本质的人,和半辈子也看不清一件事本质的人,自然是不一样的命运.

  4. ubuntu 用法

    1:改变某一个目录的拥有者 sudo chown -hR user:user ./目录名    //     user:user  用户名:组名 sudo chmod  777 文件     //给文 ...

  5. php获取目录下所有文件路径(递归)

    <?php function tree(&$arr_file, $directory, $dir_name='') { $mydir = dir($directory); while($ ...

  6. PAT 1065 A+B and C[大数运算][溢出]

    1065 A+B and C (64bit)(20 分) Given three integers A, B and C in [−2​63​​,2​63​​], you are supposed t ...

  7. 关于c语言struct和typedef

    C++中使用: struct test{    int x, y;};就可以定义一个名为 test的结构体,但C中很可能编译通不过.C语言并不支持在struct后使用标示符定义结构体的名字,test将 ...

  8. C++类型前置声明

    前言 本文总结了c++中前置声明的写法及注意事项,列举了哪些情况可以用前置声明来降低编译依赖. 前置声明的概念 前置声明:(forward declaration), 跟普通的声明一样,就是个声明, ...

  9. (转)SSIS处理导入数据时, 存在的更新, 不存在的插入

    问题描述: 当你把数据从其他数据库, 或者是文本文件之类的其他数据源导入到目的数据库时, 有时希望在导入的处理中, 能够实现"数据存在时更新, 不存在时导入" 在之前, 一般是通过 ...

  10. Android实现录屏直播(一)ScreenRecorder的简单分析

    http://blog.csdn.net/zxccxzzxz/article/details/54150396 Android实现录屏直播(一)ScreenRecorder的简单分析 Android实 ...