【问题标题】:How to restrict Child Class from accessing super Class methods?如何限制子类访问超类方法?
【发布时间】:2014-07-15 09:35:49
【问题描述】:

例如:

我有课

package test.inheritance.checkMultiple;

public class Company {



protected void run (){
    System.out.println("Time to Run");
}

}

public class Department extends Company {



    public void testDepartment()
    {
        Department d =new Department();
        d.run();
    }

}


public class Employee extends Department{


    public void checkValidEmployee(){
        Employee e =new Employee();
        e.run();
        e.testDepartment();

    }

    public static void main (String[] artgs)
    {
        Employee e =new Employee();
        e.checkValidEmployee();
        System.out.println("Valid Emplyee");
    }

}

1) 我不希望员工类有权访问运行方法。我该怎么办?

2) 如果我想给员工类访问运行方法,而不是部门类,我该怎么办?

【问题讨论】:

  • 也许你应该使用组合而不是继承?
  • 一家公司包含部门,部门包含员工。它们不形成继承层次结构。
  • 您到底希望您的 Employee 类做什么?您的意思是您不希望 checkValidEmployees 能够调用运行?
  • 是的,这就是我想要的。
  • 我不想 checkValidEmployee() 调用 run 方法

标签: java class oop


【解决方案1】:

您不应该这样做,因为每个子类都必须是其子类的有效类 - 请参阅 Liskovs substitution principle

所以使用组合而不是继承,正如@Michael Laffargue 所建议的那样。

我不知道你到底想实现什么,但它应该看起来更像下面这样,其中 Company 是 Department 的成员变量,而 Department 又是 Employee 的成员变量。

import java.util.Arrays;
import java.util.List;

public class Company
{
    private final String name;

    public Company(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return this.name;
    }

    public void run()
    {
        System.out.println("Time to Run");
    }
}

public class Department
{
    private static final List<String> VALID_DEPARTMENTS = Arrays.asList("IT");
    private final String name;
    private final Company company;

    public Department(String name, Company company)
    {
        this.name = name;
        this.company = company;
    }

    public String getName()
    {
        return this.name;
    }

    public Company getCompany()
    {
        return this.company;
    }

    public void checkValid()
    {
        if (!VALID_DEPARTMENTS.contains(this.name))
            throw new AssertionError();
    }

}

public class Employee
{
    private final Department department;
    private final String name;

    public Employee(String name, Department department)
    {
        this.department = department;
        this.name = name;
    }

    public void checkValid()
    {
        this.department.getCompany().run();
        this.department.checkValid();
    }

    public Department getDepartment()
    {
        return this.department;
    }

    public String getName()
    {
        return this.name;
    }
}

public class Main
{
    public static void main(String[] artgs)
    {
        final Company company = new Company("Company");
        final Department department = new Department("IT", company);
        Employee e = new Employee("Peter", department);
        e.checkValid();
        System.out.println("Valid Emplyee");
    }
}                                                                                                                                                                                                                                                                                                                                                                                   

【讨论】:

  • +1 表示正确的设计原则,而不仅仅是重复对错误陈述问题的琐碎答案。
  • @flob 可以请帮助我如何使用组合实现相同的效果
  • 如果我知道你在做什么,你的用例是什么?
  • @flob 部门可以更改名称,员工可以更改名称(例如婚姻)和部门。这些字段不应该是final(只是说)
  • 仅以它为例,组合和继承之间的区别是什么。其他一切都取决于您:-)
【解决方案2】:

您可以将方法声明为私有,子类将看不到它。

您也可以使用默认修饰符(包)并将子项放在不同的包中。

【讨论】:

  • 我给你投了赞成票,因为你投了反对票,尽管这是问题的答案:)
  • @Rafael 我已经将公司和部门放在一个包中,而将员工放在另一个包中
  • 是的,但是您应该删除“public”才能使用默认范围。
  • @Rafael 我尝试将类转换为默认范围并将方法转换为受保护但它不起作用我仍然可以访问运行方法
  • 我的意思是方法修饰符不是类修饰符。受保护的方法将不起作用,因为“受保护”的目的是子类甚至可以从另一个包访问父方法。
【解决方案3】:

只需将您不希望子类访问的方法声明为private。当您对某些方法使用private 访问说明符时,该特定方法不会被子类继承。您可以请参阅下表以了解访问说明符的工作原理

也研究这个链接http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

【讨论】:

  • 我已经将公司和部门放在一个包中,而将员工放在另一个包中
猜你喜欢
  • 2014-10-04
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
  • 2017-08-22
  • 1970-01-01
  • 2017-12-09
相关资源
最近更新 更多