为什么在Java子类中可以更轻松地访问字段或方法的级别

时间:2018-10-05 15:37:46

标签: java access-modifiers

据我所知,Substitution原则不允许子类具有访问权限较弱的字段,因为否则可能会破坏信息隐藏,并且还因为子类应始终提供与其至少相同的行为父母之一。对我来说很有意义。
但是同时我不明白扩展字段或方法访问级别的合理性吗?我在父班有一个私人领域,而在孩子班则是公共领域。您能举个例子说明为什么这样有意义吗?还是仅仅是出于设计选择?

3 个答案:

答案 0 :(得分:1)

这不是您在私有字段中提到的那样。您不能将私有字段从超类扩展到子类。如果声明具有相同名称的字段,则为该子类定义一个新字段。
但是,您可以更改程序包的访问权限和受保护的访问权限,例如public之类,这不会造成任何问题,因为超类不为其子类提供该类,但是子类可能会根据其状态更改其行为,并希望为其他用户。
例如,在受保护的情况下,您只能在该程序包和子类中进行访问。但是,也许您在其中做了一些不利于公共实施的工作。 (如果将某些内容公开,则必须为将来的发行版提供支持),但是在子类中,您可能需要覆盖它并为其添加一些新功能,并提供可供其他人使用的结果。
一个很好的例子(java总是提供最好的例子):
如果看到的话,java在Object类中声明了这一点:

class Object {
    protected native Object clone() throws CloneNotSupportedException;
}

所以没有人可以在上面拨打clone()。很好,因为也许我不想在课堂上提供clone()。但是,如果我愿意的话,可以很容易地覆盖它并使其对其他人公开,并在其中调用super.clone()以供使用,该功能是在创建类的新副本之前实现的。不好吗?!

答案 1 :(得分:0)

  

它可能会违反信息隐藏

信息隐藏虽然是一种很好的做法,但与Liskov替换原则无关。

  

(A)子类应始终提供至少与其父类(类)相同的行为。

这是正确的,但是可以通过在继承的成员上禁止使用 stricter 访问修饰符来实现。 较弱访问修饰符会显示其他行为。

class A {
    private int lastInput;
    protected int getLastInput() {
        return lastInput;
    }
    public int getSquareValue(int input) {
        lastInput = input;
        return getLastInput()*getLastInput();
    }
}

class B extends A {
    public int getLastInput() {
        return super.getLastInput();
    }
}

A aa = new A();
B bb = new B();
A ab = bb;

// All behaviors of A exist in B as well.
// B can be substituted for A.
System.out.println(aa.getSquareValue(5)); // 25
System.out.println(ab.getSquareValue(5)); // 25

// B also has new behaviors that A did not surface.
// This does not prevent B from substituting for A.
System.out.println(bb.getLastInput()); // 5

答案 2 :(得分:0)

https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html

父级和子级有2个单独的测试实例。如您在本例中所见。

public class Main {

    public class Parent{
        private String test = "parent test";

        String getTest() {
            return test;
        }
    }

    public class Child extends Parent {
        public String test = "child test";  // defining it here hides the parent field

        @Override
        String getTest() {
            return test;
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        Parent parent = main.new Parent();
        System.out.println(parent.getTest());

        Child child = main.new Child();
        System.out.println(child.getTest());
    }
}

输出:

parent test
child test