Java Casting to superclass不会改变对象类型?

时间:2017-07-04 15:10:18

标签: java polymorphism

我不明白为什么这段代码输出错误。 Java使用对象类型(非引用)来选择要执行的[instance]方法,在这种情况下,初始对象类型是Owl (方法返回false),无论如何,我们把这种类型转换为“Nocturnal”(没必要,但我们这样做)。我在接口和类中有 isBlind()方法。

如果对象类型现在是Nocturnal且Nocturnal方法打印为true,为什么我们Owl使用显式Cast转换为Nocturnal为false?

interface Nocturnal {
    default boolean isBlind() {
        return true;
    }
}

public class Owl implements Nocturnal {
    public boolean isBlind() {
        return false;
    }

    public static void main(String[] args) {
        Nocturnal nocturnal = (Nocturnal) new Owl();
        System.out.println(nocturnal.isBlind());
    }
}

3 个答案:

答案 0 :(得分:2)

考虑OO编程的一种强有力的方法是将方法调用视为消息传递。您向对象发送消息"请告诉我isBlind()方法的结果"。该对象进入"好的,我知道如何做isBlind(),然后执行,然后向包含结果的调用者发送消息。

您的Owl对象收到要求运行isBlind()的消息。它并不关心它来自何处。它不知道调用者对它的了解。它只运行自己的isBlind()版本并将结果发回。

当您在调用者中强制转换为超类(或接口)时,调用者会忘记"它正在与Owl交谈,但Owl并不知道。它只是像往常一样处理消息。

这是使多态性如此强大的核心。这意味着您可以将Owl放入Nocturnal的集合中,并在每个isBlind()上调用 List<Nocturnal> animals = new ArrayList<>(); animals.add(new Owl()); animals.add(new Bat()); for(Nocturnal animal : animals) { System.out.println( "Name: " + animal.getName() + " Blind: " + animal.isBlind()); } ,从而获得正确的结果:

interface

随着面向对象编程的进步,您会遇到很多无法实现这种情况的情况。尤其是单元测试,您可以将 test double (有时是 mock )替换为与您正在测试的对象协作的对象。

请注意,现代Java程序员往往不会经常进行子类化,而是倾向于在很多时候实现def show @project = Project.find(params[:id] @contractors = @project.contractors end 。 &#34;首选组合继承&#34;。同样的原则适用于多态性。

答案 1 :(得分:1)

虽然您将Owl转换为Nocturnal,但Owl对象仍包含其方法。这就是它打印false -

的原因
Nocturnal nocturnal = (Nocturnal) new Owl(); 

此处的转换只是使新创建的Owl对象与Nocturnal引用兼容 - “nocturnal

因此,当您调用isBlind()的方法时,您实际上正在调用isBlind() Owl的{​​{1}}对象,该对象仅由Nocturnal类型的nocturnal引用(或存储) 。在这里我们说动态多态是发生的。

答案 2 :(得分:1)

当子类覆盖其基类的方法时,从子类外部(包括基类)每次调用重写方法将始终导致调用overriden方法。

铸造对方法的行为没有影响。如果它覆盖了外部世界的覆盖。

根据基类提供的行为调用方法的唯一方法是在子类的实例方法中使用super关键字和.(点运算符)。