【问题标题】:Why can the level access of a field or method be more accessible in a java subclass为什么在java子类中可以更容易访问字段或方法的级别访问
【发布时间】:2019-03-11 04:00:28
【问题描述】:

据我所知,替换原则不允许子类具有访问权限较弱的字段,否则可能会违反信息隐藏,而且子类应始终提供至少与其相同的行为父母一。这对我来说很有意义。
但同时我不明白扩展字段或方法访问级别有什么意义?我在父类中有一个私有字段,而在子类中有一个公共字段。你能举个例子说明为什么这是有道理的吗?还是仅仅因为设计选择?

【问题讨论】:

  • 方法也可以,同理。
  • 如果父级有私有字段,则子级无权访问它。孩子做一个同名的公共变量是没有问题的。
  • 您不能更改字段的访问级别;您只能隐藏它并定义一个具有相同名称的新字段(这是您通常应该避免的一罐蠕虫)。你是在谈论方法吗?

标签: java access-modifiers


【解决方案1】:

正如您提到的私有领域,这不是真的。您不能将私有字段从超类扩展到子类。如果您声明具有相同名称的字段,则为该子类定义一个新字段。
但是,您可以将包访问和受保护的访问更改为更像公共的东西,这不会产生任何问题,因为超类没有为其子类提供该功能,但子类可能会根据其状态更改其行为并希望为其他用户。
例如,当它受到保护时,您只能在该包和子类中访问它。但是,也许您在其中做了一些不利于公共实施的工作。 (如果您公开某些内容,则必须支持它以供将来发布)但是在子类中您可能希望覆盖它并为其添加一些新功能并提供可供其他人使用的结果。
一个很好的例子(Java 总是提供最好的例子):
如果你看到了,java 在 Object 类中声明了这个:

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

所以没有人可以打电话给clone()。这很好,因为也许我不想为我的班级提供clone()。但是,如果我想要它,很容易覆盖它并将其公开给其他人,并在其中调用super.clone() 以使用之前实现的功能,以创建我的班级的新副本。不是很好吗?!

【讨论】:

  • "如果你用那个名字声明同一个字段,你将为具有公共级别访问权限的子类定义它"我建议把它改成"如果你声明一个具有相同名称的字段,您为该子类定义一个新字段”.
  • 感谢@MarkRotteveel 提供更好的句子。
  • @Amin 是的,我意识到 private -> public 的示例很糟糕,但是在超类中受保护而在子类型中受保护的方法呢?有意义吗?
【解决方案2】:

它可能会违反信息隐藏

信息隐藏虽然是一种很好的做法,但与 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

【讨论】:

  • 谢谢。所以不可能有一个父类有一个protected方法,一个子类有一个和public相同的方法?
  • 没有。在 Java 中,子类可以使用公共方法覆盖的受保护方法的父类。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    相关资源
    最近更新 更多