【问题标题】:Using a Superclass's getClass method from a Subclass object从子类对象使用超类的 getClass 方法
【发布时间】:2018-09-26 19:57:14
【问题描述】:

我一共有三门课。主要、动物(超类)和猫(子类)。 当我尝试调用 whatIsTheClass() 方法时,我不理解输出“Cat”。我期待看到输出“动物”。我期望输出“Animal”的原因是因为我相信方法 whatIsTheClass() 是从 Animal 对象而不是 Cat 对象调用的,因为 Subclass 不包含此方法。

主类:

package com.example.java;

public class Main {

 public static void main(String[] args) {
     Animal cat = new Cat();
 }

}

猫类:

package com.example.java;

public class Cat extends Animal {

 public Cat() {
     super();
     whatIsTheClass();
 }

}

动物类:

package com.example.java;

public class Animal {

 public void whatIsTheClass() {
     System.out.println(this.getClass().getSimpleName());
 }

}

我的理解是在继承中,子类不会复制超类的方法。如果 Subclass 对象中没有定义被调用的方法,它将在 Superclass 对象中查找被调用的方法。如果被调用的方法是在超类对象中定义的,它将从那里被调用。在这种情况下,由于子类没有定义它自己的 whatIsTheClass() 方法,它必须使用在超类对象中定义的 whatIsTheClass() 方法。但是如果从超类对象调用whatIsTheClass(),为什么返回的是子类的名字而不是超类的名字呢?

【问题讨论】:

  • 你的理解有误。这根本不是多态性的工作原理。你的对象是一只猫。 Cat 从其超类继承 whatIsTheClass 方法。 this 是当前对象,当前对象是一只猫(因为你是使用new Cat() 创建的),所以它的类是猫。创建 Cat 时,您会创建一个 single 对象。这个对象是一只猫,也是一只动物(因为猫扩展了动物)。您不会创建两个对象。
  • 我知道“Animal cat = new Cat();”中所述的对象作为一个 Cat 对象。我正在创建两个对象,因为我正在调用 Super();第二个对象是超类对象。

标签: java oop inheritance polymorphism


【解决方案1】:

whatIsTheClass 方法可以定义在Animal 中,但在哪个类的代码getClass() 中调用没有区别。如Javadocs for getClass()中所述,这都是关于对象的运行时类型:

返回此Object 的运行时类。

cat指定的对象的运行时类型为Cat

这也是为什么没有类必须重写 getClass() 只是为了返回正确的 Class 对象。 (无论如何,getClass() 方法是final。)

【讨论】:

  • 据我了解,当调用 whatIsTheClass 方法时,您是在 Animal 对象中调用它,因为它没有在 Cat 对象中定义。这不是意味着运行时类型是 Animal 吗?我在 stackoverflow 上的另一篇文章中发现了以下内容,这可能会支持我的想法“Java 递归地一次查找一个类的方法。调用第一个匹配方法。通常,当您继承时,不会复制方法中的实际代码来自包含该方法的类。”那么这个对象不是动物吗?因为它是在 Animal 对象中执行的?
  • 不是,静态类型(编译时类型)是Animal,来自cat的类型。运行时类型是Cat,来自new Cat()。同样,这不是 在哪里 getClass() 被调用,而是关于对象的运行时类型。
  • 我了解到Animal cat的Runtime类型是Cat。但是我要说的是,我可能错了,在运行时它不包含方法 whatIsTheClass()。据我了解,此方法仅存在于 Superclass 对象中,并且由于继承,它将在运行时执行 Superclass 对象中的方法(其为运行时类型 Animal),而不是执行 Subclass 对象中的方法,因为该对象没有有方法whatIsTheClass()。
【解决方案2】:

当创建 Cat 类的对象时,超类的所有方法和字段的副本会在该对象中获取内存。这就是为什么通过使用子类的对象,您还可以访问超类的成员。 请注意,在继承期间只创建子类的对象,而不是超类。

【讨论】:

  • 但是通过调用 Super();我不是调用超类的构造函数并创建一个包含方法和字段的超类对象吗?
  • 不,它只会初始化this对象的属性,该对象引用Cat类的对象。
  • 但是如果我调用 Super();在超类的构造函数中,我将一个超类字段分配给 1,然后输出该字段的值,我得到返回的值 1。如果不创建超类对象,这是不可能的。你确定 Super();不创建超类对象?
猜你喜欢
  • 2011-04-05
  • 2020-05-03
  • 2016-01-22
  • 2017-05-13
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多