【问题标题】:Why does inherited public method manipulate the super class's private property instead of the child class?为什么继承的公共方法操作超类的私有属性而不是子类?
【发布时间】:2015-07-15 23:33:16
【问题描述】:

在下面的代码中,当我运行 Test2 时,为什么它打印 null 而不是 lol?似乎config 方法修改了Test 类的a 属性而不是Test2

那么继承那些操纵私有属性的公有方法是什么意思呢,他们为什么要这样设计Java呢?

编辑:

不得修改Test 类。我想做的是重用config 方法。我为Test2 定义了一个私有属性a,但config 只是忽略它并使用Test 之一。方法不应该使用它所在类的属性而不是继承的超类的属性吗?

public class Test {
    private String a;

    public void config() {
        a = "lol"
    }
}

public class Test2 extends Test {
    private String a;

    public void print() {
        config();
        System.out.println(a);
     }

    public static void main(String[] args) {
       print()
    }
}

【问题讨论】:

  • 因为它是继承的。
  • config 方法 is 使用它所在类的属性,并且它is 在超类中。如果您可以通过让超类中的方法操作子类中的私有字段来破坏封装,那就不好了。

标签: java inheritance private public


【解决方案1】:

简而言之,目的是封装。您不需要也不能从课堂外访问私有的东西。做你想做的事情的公认模式是使用 getter/setter:

public abstract class Test {
    public void config() {
        setA("lol");
    }

    public abstract void setA(String value);
}

public class Test2 extends Test {
    private String a;

    public void setA(String value) {
        a = value;
    }

    public void print() {
        config();
        System.out.println(a);
     }

    public static void main(String[] args) {
       new Test2().print();
    }
}

【讨论】:

  • 不,这不是我想做的。我真正想做的是使用config方法来改变Test2的属性a。方法config已经被类Test2继承了对,那么它改变的私有属性a应该是Test2之一,这不是很自然的事情吗?
  • @shady 不,因为a 属于Test2,除了为它暴露一个getter/setter 之外,你无法从Test 访问它。我已经编辑了我的答案来做你想做的事。请注意,Testabstract
  • 在我的例子中,Test 类不应被修改。我知道Test 类的属性a 不能被Test2 类访问。但我想重用config 方法,并为Test2 类定义了一个私有属性a 来做到这一点。但是config 仍然使用a 的属性Test
  • @shady 如果您根本无法更改Test,您想做的事情就无法完成。你不能覆盖 Java 中的字段,这就是为什么你必须覆盖 getter/setter。
  • 是不是说Test2虽然继承了方法config,但是没有方法config的副本。如果子类要使用属性a,那就意味着a应该继承自超类Test,这会导致Test的变化。
【解决方案2】:

似乎config方法修改了Test类的a属性,而不是Test2

没错。

为什么它打印null 而不是lol

你有两个同名的变量。一个在超类Test 中,另一个在子类Test2 中。两者都命名为a,但它们指的是不同的东西。

超类中的方法config()引用超类a,子类中的print()方法引用子类a。由于变量是私有的,因此两个方法都无法看到其他类中的变量。

他们为什么要这样设计 Java?

这就是private 的本质。别人看不到。

在我看来,您实际上想要 protected 变量的行为:

public class Test {
    protected String a;

    public void config() {
        a = "lol"
    }
}

public class Test2 extends Test {
    public void print() {
        config();
        System.out.println(a);
    }

    public static void main(String[] args) {
       new Test2().print();
    }
}

这将打印lol

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-07
    • 2014-11-24
    • 2018-07-03
    • 1970-01-01
    • 2017-04-02
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多