看到很多朋友提问“为什么子类不能访问基类的private成员”?随后看到很多朋友回答“这是规范”“这是封装的特性”类似这样的回答。我觉得大家都是对的。但是有时候您需要关注提问的重点在于why?为什么Java要这样设计private?或者是Object Oriented为啥要这样设计这样的机制?
- 封装性:首先,private成员具有良好的封装性(encapsulation)。这个性质对于良好的设计来说是个重要的要素。因为良好的封装性会减小耦合的。服务代码可以定义public函数给客户代码。这样一来客户代码可以和服务代码并行开发。更重要的是,如果修改服务代码的内部实现也不需要改动客户代码。
- 子类也是客户代码:对于客户代码的理解最直接的就是调用这个类的代码,这个很好理解。更深入的理解就可以把客户代码延伸到这个类的子类。从这一点来说子类就是基类的客户代码。你定义了一个class,在里面写了些通用的方法,甚至申明了abstract方法要求别人来继承。这个时候基类里面的protect成员就是对外的API,因为这些方法对子类来说是可见的,你不能随意改动。这个时候如果这个成员是public或者protected就可能造成麻烦。对于API来说你不能随意改动。你能设想JDK里面的有些类的API改动的情况吗?至少我会抓狂的:)
- 访问权限扩大原则:延伸话题来说,还有就是Java对override的时候访问权限的限制。大家都知道Java的访问权限从小到大是:private-> default-> protected-> public。如果要override一个基类里面的方法,那么子类的这个方法的权限不能比被override的函数权限小。这样就导致一个隐性的问题:如果你的基类有public方法,那么它的子类里面都有这个方法的public属性。你不能把基类的这个方法private化。换句话说一旦定义了public函数,它的子类都要维护这个public方法。所以就算是方法也要小心地把它设为public。
当然如果这个基类到最终的子类都是你维护,或者这个类本身就是个非public的类,那么原则可以放宽。
顺便说一下,Eclipse有自动生成标准get/set函数的功能,所以生成get/set是很容易的事情,不要为了方便把成员都变成public。
譬如写了个基类Base,然后有人继承了Base:
- public class Base {
- public String[] data;
- }
- class Sub extends Base{
- public void show(){
- System.out.println(Arrays.toString(this.getData()));
- }
- }
可是有一天你发觉用ArrayList更好,你就把Base改成:
- public class Base {
- //public String[] data;
- public ArrayList data;
- }
然后所有Base的子类都无法编译,直接调用到子类data域的类也无法编译。这就是噩梦,客户端程序员会用眼光追杀你:)
回过头来想,如果当初Base的data域是private,由get/set来访问,那么你可以轻松的修改Base, 子类无需改动:
- public class Base {
- //private String[] data;
- private ArrayList<String> data;
- public String[] getData() {
- return (String[]) data.toArray();
- }
- public void setData(String[] data) {
- this.data = new ArrayList<String>(Arrays.asList(data));
- }
- }
相关推荐
私有继承则表示基类的public和protected成员在子类中都被视为private,这意味着子类不能直接暴露这些成员给外部代码使用。虽然子类内部仍然可以访问这些成员,但对外部来说,它们不可见。私有继承通常用于“is-a”...
这种情况下,基类的私有成员即使是在派生类内部也无法直接访问,这可以被视为一种“超私有”状态。例如,在以下代码片段中,`Human` 类中的 `m_dWeight` 成员在 `Man` 类中是不可见的,即便 `Man` 是 `Human` 的派生...
1. **私有(private)成员函数**:私有成员函数在基类中是不可见的,因此子类无法直接访问。为了在子类中使用这些函数,需要通过公有或保护的接口进行间接调用,或者使用友元(friend)机制。 2. **虚函数(virtual...
例如,在 SleeperSofa 类中,子类可以访问 Bed 和 Sofa 两个基类的成员,但是只能访问 public 成员,不能访问 protected 或 private 成员。 17.6 保护继承与私有继承 保护继承和私有继承是多继承中的一种继承方式...
保护成员(protected members)与私有成员类似,不能在类的外部直接访问,但它们可以被类的子类访问。在 `disp` 函数中,虽然 `j` 是 protected 的,但由于它在类的内部,所以可以被 `disp` 函数访问。另外,子类也...
派生类可以访问基类的public和protected成员,但不能访问基类的private成员。如果基类的成员是private的,派生类无法访问该成员。 4.5 派生类的构造函数和析构函数 在派生类中,需要定义构造函数和析构函数,以便...
1. **继承中的访问控制**:派生类可以访问基类的公有和保护成员,但不能访问基类的私有成员。这保持了基类的封装性。 2. **虚函数与访问控制**:虚函数(virtual functions)的声明必须是公有的,因为它们需要在...
- 父类的私有成员不能在子类中直接访问,但可以通过公有或保护成员函数进行间接访问。 - 公有和保护成员在子类中可以被访问,但对外部代码的访问权限可能受到限制。 5. **派生类的构造函数**: - **缺省构造函数...
`base`关键字允许子类访问基类的成员,包括构造函数。以下是一个简单的例子: ```csharp public class BaseClass { public string CommonProperty { get; set; } // 基类构造函数,接受一个字符串参数 public ...
保护成员在派生类中可见,但不能直接访问,必须通过派生类的成员函数或者基类的成员函数来访问;而公有成员在派生类中依然保持公有,可以直接访问。理解这一点对于设计安全和封装良好的类至关重要。 最后,我们要...
More Effective C++的Item M26:限制某个类所能产生的对象数量,里面有一个模板类可作为基类,可作为参考学习内容,如果使用VS2005对模板类进行编译,注意类声明和定义如果分开写在.h和.cpp,子类不能只#include ...
2. 公有继承(public)是最常见的派生方式,保持基类成员的可访问性,但派生类仍然不能直接访问基类的private成员,只能通过基类的公共成员函数来访问。 在实际编程中,继承的应用非常广泛。例如,`base`类可以包含...
派生类的对象可以访问基类的public成员,但不能访问private成员。 2. 私有继承(private):私有继承时,基类的所有public和protected成员在派生类中都被视为private,因此它们对于派生类之外的对象不可见。同样,...
由于Student1是公有继承Student,因此stud可以直接访问基类的display()函数,但不能直接访问基类的私有成员变量。 示例还展示了类的保护成员,如果基类A中的成员变量x被声明为protected,那么在公有继承的派生类B中...
这种访问权限设计是为了在继承时保持数据的一致性和安全性,允许子类对基类的内部状态进行必要的操作或扩展。 然而,在.NET中,存在一种特殊情况,即`protected private`组合。这种组合在C#中并不常见,但在C++/CLI...
- 私有继承下,基类的保护成员在派生类中仍为保护成员,但基类的私有成员对派生类不可见,派生类无法直接访问。 - 这种继承模式常用于表示“is-implemented-in-terms-of”关系,即派生类是用基类的方法实现的,但...
- **私有继承(Private Inheritance)**: 私有继承下,派生类的成员不能直接访问基类的任何成员。如果派生类需要访问基类的成员,则必须通过派生类的成员函数来实现。这种继承关系通常表示为“has-a”关系。 - **...
私有继承(private)时,基类的public成员和protected成员被继承到派生类中成为private成员,基类的private成员被继承到派生类中仍为private成员。 派生类的定义 派生类的定义格式如下:class 派生类名 : [继承...
而保护成员则能在多级继承链中保持可访问性,使得子类能够合理地扩展和访问基类的特定功能,而不会破坏基类的封装性。 例如,假设有一个基类`Base`,它有一个保护的成员`protectedData`,然后有一个派生类`Derived`...
派生类的成员函数可以访问基类的public和protected成员,但不能访问private成员。通过派生类对象只能访问基类的public成员。例如,`class Rectangle: public Point`,Rectangle可以从Point中继承并添加新的功能。 2...