对于Core Java中protected的疑惑

要点:

  • 当希望超类中的某些方法允许被子类访问,或允许子类的方法访问超类的某个域,需要将这些方法或域声明为 protected。

  • Java 中的受保护部分(即声明为 protected )对所有子类及同一个包中的所有其他类都可见。

疑惑:

    ”Manager 类中的方法只能够访问 Manager 对象中的 hireDay 域,而不能访问其他 Employee 对象中的这个域。”

                                                                                                                          ——《Java核心技术  卷 I》

解析:

考虑到 Employee 和 Manager 在不同的包中:

Employee 类位于 package corejava.protect; 

package corejava.protect;

import java.time.LocalDate;

public class Employee {
    protected LocalDate hireDay;

    public Employee(int year, int month, int day) {
        hireDay = LocalDate.of(year, month, day);
    }

    public LocalDate getHireDate() {
        return hireDay;
    }
}

在 package corejava.demo; 中有 Secretary 类和 Manager 类,都继承自 Employee 类。 

package corejava.demo;

import corejava.protect.Employee;

public class Secretary extends Employee {
    public Secretary (int year, int month, int day) {
        super(year, month, day);
    }
}
package corejava.demo;

import corejava.protect.Employee;

public class Manager extends Employee {
    private Secretary secretary;

    public Manager (int year, int month, int day, Secretary secretary) {
        super(year, month, day);
        this.secretary = secretary;
    }

    public void demo() {
        System.out.println("The hiring date of manager is " + this.hireDay);
        // [Java] The field Employee.hireDay is not visible
        // System.out.println("The hiring date of secretary is " + secretary.hireDay);
        System.out.println("The hiring date of secretary is " + secretary.getHireDate());
    }

    public static void main(String[] args) {
        Secretary s = new Secretary(2018, 9, 14);
        Manager m = new Manager(2008, 9, 14, s);
        m.demo();
    }
}

正如 Manager 类中的 demo() 所示,由于 Java 中受保护的部分对所有子类可见,所以可以在子类 Manager 中通过 this.hireDay 来访问 Manager 对象中的 hireDay 域。其中关键在于,Java 中受保护部分对同一个包中其他类都可见,而 Secretary 的 hireDay 继承于 Employee,而后者位于不同的包中,所以无法直接通过 secretary.hireDay 直接访问。这种限制有助于避免滥用受保护机制,使得子类只能获得访问受保护域的权利。

书中提到,在实际应用中,要谨慎使用 protected 属性。假设需要将 Employee 类提供给其他程序员使用,而在这个类中设置了受保护的 hireDay 域。其他程序员派生出了 Manager 类和 Secretary 类。现在如果需要对 Employee 类的实现进行修改,如将 hireDay 修改为 private,通过 getHireDate 方法访问,这样就必须通知其他使用这个类的程序员不能再通过 this.hireDay 的方法访问。这违背了 OOP 提倡的数据封装原则。

由此而引申的对于 Object 类的 clone() 方法为什么通过重写 clone() 方法进行深拷贝的问题也就可以理解了。书中一段注释如下:

注释:Object 类中 clone 方法声明为 protected,所以你的代码不能直接调用 anObject.clone()。但是,不是所有的子类都能访问受保护方法吗?不是所有类都是 Object 的子类吗?幸运的是,受访问保护的规则比较微妙(见第 5 章)。子类只能调用受保护的 clone 方法来克隆它自己的对象。必须重新定义 clone 为 public 才能允许所有的方法克隆对象。

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值