刚开始接触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. SpringCloud 进阶之Hystrix(断路器)

    1. Hystrix 断路器 Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败, 比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况 ...

  2. python基础之迭代器协议和生成器

    迭代器和生成器补充:http://www.cnblogs.com/luchuangao/p/6847081.html 一 递归和迭代 略 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个ne ...

  3. 转!idea启动后发现tomcat前面出现红色或是灰色的问号

    原博文地址:https://blog.csdn.net/z_zhy/article/details/83068168 直接在idea里 点击File------settings,在搜索框直接搜tomc ...

  4. 两个提高工作效率的神器-Restlet Client和fe助手

    首先是要FQ,百度***或者直接下载蓝灯. 然后安装第一个WEB前端助手:

  5. 【Python】Python 读取csv的某行或某列数据

    Python 读取csv的某行 转载 2016年08月30日 21:01:44 标签: python / csv / 数据   站长用Python写了一个可以提取csv任一列的代码,欢迎使用.Gith ...

  6. 002-spring cache 基于声明式注解的缓存-01-Cacheable annotation

    一.简述 对于缓存声明,抽象提供了一组Java注解: @Cacheable触发缓存填充(这里一般放在创建和获取的方法上) @CacheEvict触发缓存驱逐(用于删除的方法上) @CachePut更新 ...

  7. C#+GDAL读写文件

    读取shp文件: private void btnBrower_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFil ...

  8. python3 函数即变量的使用

    函数即变量的意思是函数被使用时后面不用(),类似变量的使用,具体如下面的示例代码: def say(name): print(name) hi = say hi('你好!') def add(): p ...

  9. JPA Spring Data 概述

    JPA Spring Data : 致力于减少数据访问层 (DAO) 的开发量. 开发者唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成! 框架怎么可能代替开 ...

  10. GIT学习笔记(1):创建版本库

    GIT学习笔记(1):创建版本库 创建版本库 1.创建合适目录并初始化为仓库 版本库即需要交由Git进行版本控制的目录,其下所有文件的修改.删除,Git都能跟踪还原. 说明:初始化后,当前目录下会多出 ...