首页 > 代码库 > C++ VS Java 系列 —— 访问控制
C++ VS Java 系列 —— 访问控制
访问控制
C++和Java均具有封装概念,所以也有面向对象所具有的封装中的访问控制,这些访问控制在C++中只区分类内、类外、父子类,而在Java中进行了合理的保留和舍弃,将区分扩展到了包级,类似于C++中的命名空间。
一、针对类的成员访问控制符
C++:private(class默认)、protected、public(struct默认)
Java:private、package(默认)、protected、public
Java比C++多了一个默认的访问控制package,即包访问控制,即类内成员在本包内均可以访问。
本人认为Java改进了C++的命名空间,用包名作为名字空间名,简化了命名空间不易阅读,而且具有C++命名空间名没有的优点。引入头文件改为引入带有包名的类,使得能够根据类的全路径名轻易找到类的定义位置,而且整个工程用包进行管理,根据模块功能定义包名划分工程,能够轻易简单的将相关的类定义在同一包中,使得整个项目结构清晰,易于维护,同时到达了模块内高内聚,模块间低耦合的要求。由于同一个模块内的类是相关的,相对紧密相连的,所以将其成员变量的访问控制定义为包级访问控制时极具意义的,这样包内可见,包外不可见。
其他访问控制符作用效果一样。
二、针对接口的成员访问控制符
C++:没有接口不过可以用抽象类当做接口,不过没有Java的接口设计合理
Java:接口内所有的成员变量均是public,因为接口本身就是在模块之间、层次之间起协议作用的,并不涉及具体实现,而且协议对于双方而言都应当是公开的。
三、针对类访问控制符
C++:没有
Java:public、package
public:所有地方可见,对其他所有类暴露本类
package:包内可见,包外不可见
由于一个模块内的所有类并都不是其他模块可见,有可能仅仅为本模块所拥有,即为本包拥有,所以设计成有包区分的类是有有意义的。而C++的所有类则没有这种限制,在此,C++对类的控制力度不够,只要其他文件引入头文件,则可以使用,属于不合理的。从另外一个角度看,C++的命名空间并没用进行访问控制,均是开放的。
四、针对于类的继承的访问控制符
由于C++的访问控制包含了类的继承,对类的继承也有private(class默认)、protected、public(struct默认)继承模式。
父类对象不能用非公有继承的子类对象进行初始化或者赋值。
父类指针或者引用不能指向非公有继承的子类对象。
非公有继承的子类无法加入基于父类的多态框架中。但是私有继承可以帮助我们复用基类代码,并防止基类接口的曝光。但是父类接口对于其他类还是处于曝光状态,只是不能通过私有继承类这个渠道去曝光,所以并不是很实用,更何况有比继承耦合性更低的组合,可以达到私有继承的效果,即将父类作为子类一个私有成员,让后复用其代码。
针对于private继承,个人感觉意义不大,甚至很鸡肋,难道要子类将从父类继承过来的成员隐藏起来?父类的成员访问控制不应该自己做吗,父类对外既然都声明公开了,子类反而说要私有,这有个严重的后果,就是违反了里氏代换原则(任何基类可以出现的地方,子类一定可以出现),基类出现的地方,并且具有对其成员的访问,而子类替换基类之后(这种所说的替换是强硬替换,即所有父类对象出现的地方,全部替换成子类对象,而不是父类指针或者引用指向子类对象),由于子类将父类继承过来的成员私有化了,则会造成无法访问原本可以访问的成员的问题。这好比,上层领导给人民一个承诺,下层领导却不承认该承诺,这极其不合常理。实际上C++也不是没有作为的,C++编译器不允许使用父类指针或者父类应用指向私有继承的子类对象,并且倘若是强硬替换,也会在无权访问的地方抱错,虽然这个保证了不会违反里氏代换原则,则但是这样也是会使得该子类无法参与多态,或者说该实现无法加入由多态为基础的框架中去,从而使得C++的多态遇到了蹩脚的地方。针对protected继承,也是有存在类似问题的,不予赘述。
根据工程经验,实际工程使用过程中基本是使用public继承。估计是Java吸收了这个经验,所以Java中不存在继承访问控制,倘若要说的话,Java中所有的继承均是公有继承,子类不会改变父类对外的承诺,即子类不会改变父类的成员的访问控制
若有不正之处,请谅解和批评指正,不胜感激。
请尊重作者劳动成果,转载请标明原文链接:http://www.cnblogs.com/Isen/p/6683523.html
C++ VS Java 系列 —— 访问控制