简体   繁体   English

Java:从子类调用super.getClass()

[英]Java: Calling super.getClass() from subclass

I know this question has been already asked here , but I fail to understand the "Why" part. 我知道这个问题已在这里提出,但我不理解“为什么”部分。

Let us take the following example: 我们来看下面的例子:

public class First {
    First() {
       System.out.println(super.getClass());
    }
}

public class Second extends First {
    Second() {
       System.out.println(super.getClass());
    }
}

public class Third extends Second {
    Third() {
       System.out.println(super.getClass());
    }
}  

When I instantiate an Object of type Third: 当我实例化第三类型的对象时:

public class Main {
    public static void main(String[] args) {
        Third third = new Third();
    }
}

The output is: 输出是:

class Third
class Third
class Third  

And what I expected was (Thinking that super.getClass() should return the name of parent class): 而我的期望是(认为super.getClass()应该返回父类的名称):

class java.lang.Object
class First
class Second

Which shows that I don't understand how does Inheritance actually work in Java. 这表明我不明白继承在Java中是如何工作的。 Kindly help me in getting the right concept in my head. 请帮助我在脑子里找到正确的概念。

EDIT 编辑

My actual intention was to understand how inheritance actually works (which has been explained very well by Jeff), instead of getting the expected output. 我的目的是了解继承实际上是如何工作的(Jeff已经很好地解释了),而不是获得预期的输出。
This doubt arose when I was trying to the understand why the following code worked (More specifically, why does super.equals(point3d) worked as it has been passed an object of type Point3D) 当我试图理解为什么下面的代码工作时会出现这种疑问(更具体地说,为什么super.equals(point3d)工作,因为它已经传递了Point3D类型的对象)

public class Main {
    public static void main(String[] args) {
        Point3D p1 = new Point3D(1, 2, 3);
        Point3D p2 = new Point3D(1, 2, 3);
        System.out.println(p1.equals(p2));  // Output: true
    }
}

public class Point {
    private int x;
    private int y;

    public Point() {
        this.x = 0;
        this.y = 0;
    }

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object object) {
        if (object != null && object.getClass() == this.getClass()) {
            Point point = (Point) object;
            return point.x == this.x && point.y == this.y;
        } else {
            return false;
        }
    }
}

public class Point3D extends Point {
    private int z;

    public Point3D() {
        this.z = 0;
    }

    public Point3D(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }

    @Override
    public boolean equals(Object object) {
        if (object != null && object.getClass() == this.getClass()) {
            Point3D point3D = (Point3D) object;
            return super.equals(point3D) && point3D.z == this.z;  // Had doubt here
        } else {
            return false;
        }
    }
}

It is important to recognize that there is exactly one object here with one reference . 重要的是要认识到这里只有一个对象有一个参考 It can be tempting to present it as though the superclass is a separate instance of Second residing within your instance of Third, but it is not true; 它可能很诱人,就好像超类是第二个驻留在你的第三个实例中的第二个实例,但它不是真的; there is no way to refer to that instance because it does not exist. 没有办法引用该实例,因为它不存在。

To be clear: It is not the case that within Third there is a hidden instance of Second to which super refers, and within Second there is a First, and within First there is an Object. 需要明确的是: 在第三种情况下,不存在super引用的第二个隐藏实例,而第二个内部存在第一个,第一个内部存在一个对象。 Instead, there is a single object that is able to behave as an Object, First, Second, or Third. 相反,有一个对象可以表现为Object,First,Second或Third。 Regardless of the type of the local variable or reference ("static type"), the instance itself has a "runtime type", which is Third. 无论局部变量或引用的类型(“静态类型”),实例本身都具有“运行时类型”,即第三个。

The only thing super can do for you is to deliberately invoke a member that belongs to a superclass (JLS 15.11.2) that may be hidden by overriding or naming. super可以为您做的唯一事情是故意调用属于超类(JLS 15.11.2)的成员,该成员可能被覆盖或命名隐藏。 This does nothing here, because getClass() is a final method declared on Object. 这里什么都不做,因为getClass()是在Object上声明的final方法。 getClass has documentation that it "Returns the runtime class of this Object" ( docs ). getClass文档是“返回此Object的运行时类”( docs )。 There can be no varying implementation, so you will always receive the type Third as you do in your question. 没有不同的实现,因此您将始终像在问题中一样收到第三类。


UPDATE: Unlike getClass , equals is non- final , and can be overridden. 更新:getClass不同, equals是非final ,可以被覆盖。 Point.equals ensures that the Class returned by getClass is equal, and that x and y are equal. Point.equals确保getClass返回的Class相等,并且xy相等。 Rather than writing an entirely different implementation of equals , Point3D defers to the Point's definition of equals and additionally checks that the z field is equal, which works because Point checks that object.getClass() == this.getClass() , not that object.getClass() == Point.class . 而不是写一个完全不同的equals实现,Point3D遵循Point的equals定义,并另外检查z字段是否相等,这是因为Point检查object.getClass() == this.getClass() ,而不是那个object.getClass() == Point.class It could not do this simply by calling equals , because that would use the Point3D.equals implementation; 它不能简单地通过调用equals做到这一点,因为那将使用Point3D.equals实现; instead it has to call super.equals to see how Point would calculate equals . 相反,它必须调用super.equals来查看Point如何计算equals

However, I hope this is an example in a lesson, because polymorphism asserts that a Point3D is-a Point and can do whatever a Point can do (see the Liskov Substitution Principle ). 但是,我希望这是一个教训中的一个例子,因为多态性断言Point3D是一个Point并且可以执行Point可以做的任何事情(参见Liskov替换原则 )。 For Point and Point3D, this could be misleading: You could write a method double distanceBetween(Point a, Point b) that works as expected using 2D points but gives an incorrect result when using 3D points. 对于Point和Point3D,这可能会产生误导:您可以编写一个方法double distanceBetween(Point a, Point b) ,它使用2D点按预期工作,但在使用3D点时会产生错误的结果。 In real environments, you'll need to be careful about what your class hierarchies and what they imply. 在实际环境中,您需要注意您的类层次结构及其含义。

getClass() is a method on Object . getClass()Object上的一个方法。 There's not a separate one for each of your subclasses. 每个子类都没有单独的一个。 If you want to go up the chain like that, call getSuperclass() on the result of getClass() . 如果你想像这样上链,请在getClass()的结果上调用getSuperclass() getClass()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM