首页 / 知识
关于oop:是否应该禁止受保护的属性?
2023-04-16 03:59:00

Should protected attributes always be banned?我很少使用继承,但是当我这样做时,我从不使用受保护的属性,因为我认为它打破了继承类的封装。 你使用受保护的属性吗? 你用它们做什么的? 在Bill Venners的设计访谈中,Effective Java的作者Joshua Bloch说:
简短版本:它打破了封装,但它是一个必须保持最低限度的必要的邪恶。 C#: 我将protected用于抽象或虚拟方法,我希望基类重写。如果它可以被基类调用,我也会使方法受到保护,但我不希望它在类层次结构之外调用。 您可能需要它们用于静态(或"全局")属性,您希望您的子类或来自相同包的类(如果它是关于Java)受益。 表示某种"常量值"的静态最终属性很少有getter函数,因此受保护的静态final属性在这种情况下可能有意义。 Scott Meyers说不要在Effective C ++中使用受保护的属性(第3版):
原因与您给出的相同:它打破了封装。结果是,否则对类布局的局部更改可能会破坏依赖类型并导致许多其他位置的更改。
它不是破坏封装的受保护成员,它暴露了不应暴露的成员破坏了封装...它们是受保护还是公共无关紧要。 拥有受保护的属性从来没有任何充分的理由。基类必须能够依赖于状态,这意味着通过访问器方法限制对数据的访问。你不能让任何人访问你的私人数据,甚至是儿童。 我最近在一个项目上工作过的"受保护"成员是一个非常好的主意。类层次结构是这样的:
Base实现了一个std :: list但没有别的。用户禁止直接访问列表,但由于Base类不完整,因此无论如何它依赖于派生类来实现对列表的间接访问。 间接可以来自至少两种风格:std :: map和stdext :: hash_map。两个映射的行为方式都相同,但事实上hash_map需要Key可以清除(在VC2003中,可转换为size_t)。 因此BaseMap将TMap实现为模板化类型,它是类似地图的容器。 Map和HashMap是BaseMap的两个派生类,一个在std :: map上专门定位BaseMap,另一个在stdext :: hash_map上。 所以:
对我来说,唯一的解决方案是对std :: list和TMap成员变量使用protected。我无法将这些"私有"放在那里,因为无论如何我都会通过读/写访问器公开所有或几乎所有的功能。 最后,我想如果你把你的类分成多个对象,每个派生都需要为它的母类添加所需的特性,并且只有最派生的类才真正可用,那么保护就是要走的路。事实上,"受保护的成员"是一个阶级,因此几乎不可能"打破",帮助。 但是,应尽可能避免受保护(即:默认情况下使用私有,并且必须公开方法时公开)。 我认为受保护的属性是个坏主意。我使用CheckStyle与我的Java开发团队一起强制执行该规则。 通常,您真的不想使用受保护的数据成员。如果您编写API,这是双重的。一旦有人从你的班级继承,你就永远不会真正做到维护,也不会以某种奇怪的,有时是狂野的方式打破它们。 我不在Java中使用受保护的属性,因为它们只受到包保护。但是在C ++中,我将在抽象类中使用它们,允许继承类直接继承它们。 我在基类中使用受保护的变量/属性,我知道我不打算更改为方法。这样,子类可以完全访问其继承的变量,并且没有(人为创建的)通过getter / setter访问它们的开销。一个例子是使用底层I / O流的类;没有理由不允许子类直接访问底层流。 这适用于在基类和所有子类中以直接简单方式使用的成员变量。但是对于使用更复杂的变量(例如,访问它会导致类中其他成员的副作用),直接可访问的变量是不合适的。在这种情况下,可以将其设为私有,并且可以提供公共/受保护的getter / setter。一个示例是基类提供的内部缓冲机制,其中直接从子类访问缓冲区会损害基类用于管理它们的算法的完整性。 这是一个设计判断决策,基于成员变量的简单程度,以及未来版本中预期的结果。 封装是很好的,但它可以采取太多。我见过自己的私有方法只使用getter / setter方法访问其成员变量的类。这是过度的,因为如果一个类不能信任自己的私有方法和它自己的私有数据,它可以信任谁?
这取决于你想要什么。如果你想要一个快速类,那么应该保护数据并使用protected和public方法。 如果您的用户弄乱了您的课程,那不是您的问题。在覆盖其中一个虚拟机时,每个恶意用户都可以添加以下行: (C#)
你不能密封每一堂课以防止这种情况发生。 当然,如果您想要对某些字段进行约束,那么请使用存取函数或属性或您想要的东西,并将该字段设为私有,因为没有其他解决方案...... 但我个人不喜欢不惜一切代价坚持oop原则。特别是制作属性的唯一目的是使数据成员私有化。 (C#):
这是我个人的意见。 但要做你的老板要求(如果他想要私人领域而不是那样做。) 一般来说,是的。受保护的方法通常更好。 在使用中,通过对一个类的所有子级共享的对象使用受保护的最终变量,可以实现一定程度的简单性。我总是建议不要将它与原语或集合一起使用,因为合同不可能为这些类型定义。 最近,我将你用原型和原始集合与你用格式良好的类做的东西分开。原始和收藏品应始终是私人的。 此外,我偶尔会在公共成员变量声明为final时公开它们,并且是格式良好的类,它们不是太灵活(同样,不是原语或集合)。 这不是一些愚蠢的捷径,我认为它非常认真,并且决定暴露一个对象和一个getter的公共最终变量之间绝对没有区别。 我用它们。简而言之,如果您想要共享一些属性,这是一个好方法。当然,您可以为它们编写set / get函数,但如果没有验证,那么重点是什么?它也更快。 考虑一下:你有一个类是你的基类。它有很多属性你不想在子对象中使用。你可以为每个编写一个get / set函数,或者你可以设置它们。 我的典型示例是文件/流处理程序。您想要访问处理程序(即文件描述符),但是您想要将其从其他类中隐藏。这比为它编写set / get函数更容易。 |
最新内容
相关内容
linux命令api封装?
linux命令api封装?,地址,软件,标准,系统,入口,设备,服务,工作,通信,环境,liunx系统中调用Api接口API就是操作系统留给应用程序的一个调用接口,linux禁止rm命令?
linux禁止rm命令?,系统,命令,文件,情况,状态,基础,数据,实时,工作,目录,linux删除命令rm的技巧介绍Linux rmdir命令:删除空目录(空的文件夹)mdilinux中的封装命令?
linux中的封装命令?,系统,工具,电脑,工作,信息,软件,盘中,官网,网络,名字,linux下qt制作的界面怎么封装方法是选择File→New→C++Main- File(mlinux禁止防火墙命令?
linux禁止防火墙命令?,服务,系统,信息,软件,防火墙,命令,公共,设备,终端,以上,关闭防火墙linux命令?1、linux关闭防火墙命令:service iptableslinux命令查看包属性?
linux命令查看包属性?,时间,系统,信息,状态,命令,文件,通讯录,管理,情况,标准,Linux文件相关命令命令一:cat cat命令应该是在Linux中查看文件内linux封装全局命令?
linux封装全局命令?,系统,工作,地址,工具,电脑,软件,信息,命令,代码,数字,如何重新封装linux系统成iso文件打开制作iso镜像文件工具,在软件界面linux内核属性命令?
linux内核属性命令?,系统,地址,时间,信息,标准,管理,数据,工作,百分比,内核,一般优化linux的内核,需要优化什么参数1、说起优化,其实最好的优化linux禁止重启的命令?
linux禁止重启的命令?,系统,时间,命令,银河,灵活,工作,代码,用户,终端,麒麟,关闭linux系统不重新启动可使用什么命令使用shutdown命令可 以直linux禁止休眠命令?
linux禁止休眠命令?,系统,服务,状态,工作,网络,标准,意外,设备,定期,百分比,获取linux系统是否休眠第二行:Tasks 任务(进程),系统现在共有183个进pythonPandas Series对象有哪些属
pythonPandas Series对象有哪些属性?,工具,数据,数字,分析,培训,属性,数据类型,数组,对象,索引,想必大家都知道pandas,它是基于Numpy的一种工具如何在Python中定义类方法和修改类
如何在Python中定义类方法和修改类属性?,代码,方法,培训,对象,实例,定义,结果,示例,赋值,属性,Python中的类还可定义使用@classmethod修饰的类Python __dict__属性详解
Python __dict__属性详解,代码,公用,信息,数据,培训,管理,属性,对象,函数,结果,我们都知道Python一切皆对象,那么Python究竟是怎么管理对象的