【问题标题】:how does base class know about sub class method?基类如何知道子类方法?
【发布时间】:2013-06-17 00:56:12
【问题描述】:
public class BaseClass {
    private String className;

    public BaseClass() {
        className = "[BaseClass]";
    }

    public void executeAB() {
        System.out.println(className + " executingAB()");
        executeA();
        executeB();
    }

    public void executeA() {
        System.out.println(this.className + " executingA()");
    }

    public void executeB() {
        System.out.println(this.className + " executingB()");
    }
}


public class SubClass extends BaseClass {

    private String className;

    public SubClass() {
        this.className = "[SubClass]";
    }

    public void executeA() {
        System.out.println(className + " executingA()");
    }

    public void executeC() {
        System.out.println(className + " executingC()");
    }

    public static void main(String[] args) {

        BaseClass t = new SubClass();
        t.executeAB();
        // t.executeC();
    }
}

在上述情况下,调用 t.executeAB() 会导致输出:

[BaseClass] 执行AB()

[子类]执行A()

[BaseClass] 执行B()

我的问题是:

BaseClass 如何知道 SubClass 的 excuteA() 方法,同时 t.executeC() 调用是 not possible 因为 BaseClass 不知道 executeC()。

【问题讨论】:

  • 答案是 BaseClass 知道如何或是否重写方法,而 OOP 的魔力在于它不必知道。这一切都由dynamic dispatch table 方法在幕后处理。
  • 这是在 OOP 中具有继承的基本原因之一。

标签: java oop inheritance overriding


【解决方案1】:

您对继承时应该做什么有误解。 extends 是明智选择的保留字。 B 扩展 A 的意义在于 B 是具有附加属性的 A 的子集。您不应该在 B 中重新定义 x; A 应该处理 x。你不应该在两个类中声明className

至于你的例子:

 BaseClass t = new SubClass(); 

调用SubClass 的构造函数,将SubClassclassName 设置为[SubClass]。也调用了超级构造器,将BaseClass中的className设置为[BaseClass]

 t.executeAB();

打印BaseClass 的类名[BaseClass],然后调用:

 executeA(); 
 executeB();

executeA() 是从 SubClass 调用的,因为 t 是 SubClass 并且它已定义,所以我们得到 [SubClass],最后,executeB() 是从 BaseClass 调用的,所以再一次,我们得到 @987654343 @。至于为什么不能打电话:

t.executeC()

尽管使用SubClass 的构造函数,tBaseClass。根据OOP的原则,你不能调用t.executeC()是有道理的,因为它没有为BaseClass定义。

【讨论】:

  • 谢谢史蒂夫。您提到“您不应该在 B 中重新定义 x”,那么覆盖有什么用?你的意思是我应该重写 executeAB() 吗?
  • Overriding 用于重新定义子类中的方法。例如,覆盖toString() 是有意义的,因为我们希望能够拥有对象的String 表示(可能需要不同于我们父级的toString())。我不确定你的意图是什么,但你永远无法在BaseClass 上调用executeC(),除非它在BaseClass 或其超类之一中定义......另外,因为你是新的,你应该看看tour
【解决方案2】:

您将变量定义为BaseClass t = new SubClass();,这意味着您为不同的子类实例化留出了空间。但是,为了在不破坏现有代码的情况下实现这一点,您只能使用基类中定义的方法。

【讨论】:

    猜你喜欢
    • 2021-10-22
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 2012-03-09
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多