【问题标题】:Superclass and subclass resolution?超类和子类解析?
【发布时间】:2014-08-12 19:29:36
【问题描述】:

我是 java 编程新手,对 stackoverflow 也很陌生。遇到了这个我无法理解的简单代码。请帮我看看它是如何工作的

class Base {
 public static void foo(Base bObj) {
 System.out.println("In Base.foo()");
 if(bObj instanceof Base){
     System.out.println("Base instance");
 }
 bObj.bar();
 }

 public void bar() {
     System.out.println("In Base.bar()");
     }
    }
    class Derived extends Base {
     public static void foo(Base bObj) {
     System.out.println("In Derived.foo()");
     bObj.bar();
     }
     public void bar() {
     System.out.println("In Derived.bar()");
     }
    }
    class Downcast {
     public static void main(String []args) {
     Base bObj = new Derived();
     bObj.foo(bObj);
     }
    }

现在我明白了

In Base.foo()
Base instance
In Derived.bar()

虽然我知道它是如何进行的base.foo()。但是它是如何派生的。它还打印出它是一个基础对象的实例,然后是如何派生的。给出的解释是,它之前进行了静态解析,后来进行了动态解析。什么是静态的和动态分辨率。

虽然这个概念是这样的

Base b=new Derived();

这意味着我们创建了一个派生对象,然后将其向上转换为 Base。那么为什么不调用 base.bar() 呢?

提前致谢。

【问题讨论】:

  • static 方法未被覆盖。如果你在子类中声明了一个static 方法,它与父类中的static 方法具有相同的签名,则称为隐藏它。
  • 你的意思是子类中的静态方法隐藏还是父类?
  • 子类方法隐藏父类方法。多态性也不适用于static 方法。

标签: java inheritance base derived-class


【解决方案1】:

您已经发现了静态方法和非静态方法之间的区别。

静态方法是根据调用它们的类的类型来调用的。例如,在您的情况下,Base b = new Derived();b.staticMethod() 是从 Base 调用的。这就是为什么你永远不应该从对象调用静态方法的原因——这是不必要的,因为你可以调用 Base.staticMethod()

但是,如果调用b.nonstaticMethod(),则会调用派生类中的非静态方法。这就是 Java 管理继承的方式。

为了进一步阅读,我建议阅读Java Tutorial on Inheritance

【讨论】:

    【解决方案2】:

    这就是多态性的核心。 Java 中的对象试图表现得与真实对象相同。

    自行车通常有 3 个齿轮。

    竞赛用自行车是自行车。但他们有 18 个齿轮。

    如果我向您展示一辆竞赛自行车并问您“它是自行车吗”,答案是肯定的,对。但是如果我问你“这辆自行车有多少个齿轮”,你会回答“18”,因为它虽然是一辆自行车,但它是一种特殊类型的自行车,它不像普通自行车那样有3个齿轮,而是18个。

    Java 对象也是如此:

    Base bObj = new Derived();
    

    相同
    Bike bike = new CompetitionBike();
    

    即您正在建造一辆自行车,而自行车的具体类型是“竞赛自行车”。所以,如果你问自行车有多少档位,答案是 18:

    bike.getGears(); // 18
    

    同样,

    bObj.bar();
    

    将调用在对象的具体类型中定义的 bar() 方法,该类型是 Derived。所以会打印“In Derived.bar()”。

    静态方法不遵循这些规则,因为静态方法不是在对象上调用,而是在类上调用。

    拨打bObj.foo(bObj) 是合法的,但这种做法非常糟糕。您应该调用的是Base.foo()Derived.foo(),具体取决于您要调用的方法。并且将调用给定类上定义的方法。当你做错误的事情并调用bObj.foo()时,编译器实际上将bObj转换为bObj声明类型,即Base

    【讨论】:

    • Wooo..我什至没花一秒钟就明白这一切。这太棒了。
    猜你喜欢
    • 2012-10-08
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多