冒号和他的学生们(连载26)——访问控制 - 编程入门网
冒号和他的学生们(连载26)——访问控制(2)时间:2011-07-03 BlogJava 郑晖“其中public和private是两个极端,一个没有限制,一个仅限于同一类。Java和C#比C++多了个包(package或assembly)的概念,相应也多了package(缺省)和internal的修饰符。”冒号解说道,“值得注意的是,Java中的protected相当于C#的protected internal,不仅可被同类和子类访问,还能被同一包内的任何类访问。而C++和C#中的protected只能被同类和子类访问,相当于Java中昙花一现的private protected。” 逗号急欲得知:“选择这些修饰符有什么诀窍吗?” 冒号回应:“一个基本原则是尽可能地使用限制性更强的修饰符。即使以后改变主意,再放宽限制也不迟。相反,将一个修饰符收窄就要顾忌对客户的影响了。尤其是域成员,没有特殊理由都应该是private的,除非类是一个用作储存的具体数据类型或内部类(inner class)。在JDK源代码中有不少package、proctected域成员甚至public域成员,绝不能以之为榜样。顺便说一句,C++和C#中缺省的成员修饰符是private,显然比Java中缺省package更科学一些。” 问号刨根问底:“为什么特别强调域成员呢?” 冒号条分缕析:“域成员代表对象的状态,从运行方面看,若外界随意读取和改动,将无法保证内在逻辑的一致性;从设计方面看,属结构性信息,极易变化;从接口方面看,公开接口都是以方法而非域的形式出现的。这些都要求隐藏域成员。” 引号思路很清晰:“既然域成员一般都用private,那关键是如何选择方法成员的访问修饰符了。” “如果将每个类看作一个服务者,它向不同范围内的客户承诺不同的服务,或者说提供了层次化的服务。以Java为例,每一个public方法成员即是向所有类提供的服务;protected方法成员对该类的子类和同一package下的类提供服务;默认的package方法成员仅对同一package下的类提供服务;private方法成员则只对该类本身提供服务。那么如何具体界定一个服务的范围呢?大多时候这是一个伪问题。”说到这里,冒号有意停顿了一会,查看大家的反应。 众人脸上果然满是狐疑之色。 “因为合理设计的服务,其内容与范围往往是密不可分的。一个服务如果已经设计好了,甚至已经实现了,而此时尚未决定其使用者的范围,是否有些荒谬?当然,荒谬其实也是现实中的一种常态。”冒号语带反讽,“作为一个抽象数据类型的类,其核心是抽象接口,因此首先应该设计公共接口,它们的修饰符自然都是public。如果该类是一个抽象类(abstract class)——此‘抽象’与抽象数据类型的‘抽象’意义有所不同,暂且不表——那么可能会有一些为其子类提供的服务,它们的修饰符自然该是protected。” 问号听得仔细:“难道非抽象类就不能有protected的接口吗?” 冒号回道:“从语法上说当然可以。但一般不建议继承非抽象类,因而protected的意义就不大了。至于个中缘由,留待下节课再解释。” 叹号追问:“那package服务和private服务呢?” 冒号应答:“package一般作为library的单位,因此package方法成员存在的唯一理由是仅为该library服务,但这种情况相对少见。说到private方法成员,已谈不上是真正的服务,纯粹是实现细节。由于它的改动不会影响客户,因此采用private访问控制不需要任何理由,不采用它才需要理由。” 众人听得频频点头。 冒号总结道:“从软件应变的角度来看,访问控制是对修改所带来的副作用的控制。具体地说,如果修改仅仅涉及到private成员,那只要检查该类的源代码即可;如果 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |