【问题标题】:Java inheritance - please explainJava继承-请解释
【发布时间】:2009-11-15 17:20:53
【问题描述】:
class A {
    public void talk(){
        this.sayIt();
    }

    private void sayIt(){
        System.out.println("class A says...");
    }
}

class B extends A {
    private void sayIt(){
        System.out.println("class B says...");
    }
}

测试类,主要方法:

B b = new B();
b.talk() 

//output
class A says...

我无法得到这个,因为:

B 类 继承自 A 类,公共成员,不能看到/继承私有函数。所以在class B中,我们可以调用talk()。 //因为是被父类继承的。

现在,在 talk() 方法中,有一个对 sayIt() 的调用,因为 sayIt() 在 B类,

我希望在执行 this.sayIt() 时调用 B.sayIt()。

“this”不是指B类吗?

请解释一下。

【问题讨论】:

  • 那个talk方法不在类B中。

标签: java inheritance


【解决方案1】:

因为您将 sayIt() 定义为私有,所以 B 类不能覆盖它。因此,sayIt() 有两个定义,而不仅仅是一个被子类覆盖的定义。

在 A 类代码的一部分中,它总是会从 A 类调用版本,即使 B 类版本是受保护的或公开的。这是因为 A 类只知道 A 类的版本,因为 B 类的版本不是覆盖,而是一个完全不同的方法,恰好共享相同的名称。

在 B 类代码的一部分中,它总是会从 B 类调用版本,因为 A 类版本被标记为私有。正如其他人所指出的,如果您将定义更改为受保护或公开,它将对 B 类可见并且它会做您想做的事情。

请注意,如果您要使用默认(包)可见性,则范围规则会变得非常复杂,并且实际结果会有所不同,具体取决于哪些子类在同一个包中,哪些在不同的包中。

【讨论】:

    【解决方案2】:

    考虑在sayIt 上创建protected 而不是private。 B 上的 sayIt 不会覆盖 A 上的 sayIt。

    【讨论】:

    • 谢谢,但是由于从 B 的上下文中看不到 A.sayIt(),它是如何被调用的?
    • 由于 sayIt 是私有的,JVM 知道当 talk 调用 sayIt 时,它不需要查看 sayIt 的覆盖版本的任何子类,所以它直接调用 A.sayIt()。
    • 不是从B调用的,而是从A类实现的方法中调用的,可以看到A类的私有方法。
    • @andreas,A.sayIt() 被调用是因为它在 A 的上下文中是可见的,因为 A.talkIt() 在 A 上下文中。
    【解决方案3】:

    您正在尝试覆盖私有方法。没有意义。

    【讨论】:

      【解决方案4】:

      如果您将“sayIt”方法更改为受保护,它将像您期望的那样工作。

      您似乎对它如何与覆盖方法一起工作感到有些困惑。 如果我没记错的话,您尝试做的事情在 C++ 中完全没问题,但在 Java 中却不行。

      【讨论】:

        【解决方案5】:

        是的,b.talkIt() 的“this”指的是 B 类,但由于 sayIt() 在 A 中是私有的,而 talkIt() 在 A 中被贴花并且在 B 中没有被覆盖,所以 sayIt() 将被引用到A.

        你可以这样看。 A 的sayIt() 是私有的,因此不能被覆盖。由于它没有被覆盖,所以 A 的方法调用 sayIt() 将始终指向 A 已知的那个(因为它没有被覆盖)。

        希望这会有所帮助。

        【讨论】:

          【解决方案6】:

          “这个”不是指B类吗? - 不。虽然您从类 B 创建了一个实例,但您仍然引用了基类型的方法,即 talk()。实现相同目标的一种方法是通过模板方法模式。

          /BB

          【讨论】:

            【解决方案7】:

            因为 sayIt 是一个私有方法,它实际上并没有被覆盖。帮助理解这一点的一种方法是将 @Override 注释添加到您认为覆盖超类中的某些内容的任何方法中。如果你错了(如本例),那么编译器会告诉你。

            【讨论】:

              【解决方案8】:

              因为在talk 中你引用this.sayIt 而对象B 是A 的实例。

              对象 A 不知道 B 中的方法。使对象 A 成为具有 sayIt 抽象方法的抽象类,您在 A talk 中调用该抽象方法或更改 sayIt 的可见性。

              另外 - 使用注释,IDE 会通过警告通知您。

              【讨论】:

                【解决方案9】:

                根据 Java 语言规范 8.4.8:

                A class C inherits from its direct superclass and direct superinterfaces
                all non-private methods (whether abstract or not) of the superclass and
                superinterfaces that are public, protected or declared with default access
                in the same package as C and are neither overridden nor hidden by a
                declaration in the class.
                

                所以 B 没有继承 A.sayIt(),因此没有覆盖它。

                【讨论】:

                  【解决方案10】:

                  稍微偏离主题,但可以帮助您更好地理解Java继承。

                  http://webmoli.com/2008/08/02/why-multiple-inheritance-is-not-allowed-in-java/

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-04-28
                    • 1970-01-01
                    • 2014-02-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多