关于动态绑定的困惑

时间:2014-11-22 19:05:35

标签: java

正如我从教科书中学到的,如果我将类型超类的变量名称,newObject指定给类型为子类的对象,并且子类有一些重写方法,则说方法toString() ,然后当我调用newObject.toString()时,调用重写的方法,而不是原始方法。

但在另一种情况下,我没有再发生这种情况。例如,我的超类名为Ship,其子类CruiseShip

class Ship{}

class CruiseShip extends Ship implements Serializable {
    int getSize() {
        return 42;// value is not important now
    }
}

我序列化CruiseShip的实例,然后对其进行反序列化。

CruiseShip cs = new CruiseShip();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(cs);
oos.close();

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
        baos.toByteArray()));
Object obj = ois.readObject();
ois.close();

现在返回对象的类型为Object,因此我将类型转换为类型Ship,以便我可以将其分配给变量名newShip,其类型为{{1 }}。

Ship

问题是我无法调用类Ship newShip = (Ship)obj; 的某些方法,说CuiseShip

getSize()

未在超类int size = newShip.getSize();//error: method getSize() is undefined for the type Ship 中定义。只有当我将对象强制转换为Ship时,我才能调用该方法。

CruiseShip

那么,这里发生了什么?我希望动态绑定允许我使用int size = ((CruiseShip)newShip).getSize();//OK 来调用方法newShip,但事实并非如此。

2 个答案:

答案 0 :(得分:2)

这不是动态绑定的工作原理。如果该方法存在于超类中并在子类中被覆盖,那么即使在声明类型 superclass 的对象上调用,如果它实际上是将调用类型子类而不是子类的方法。但是,如果该方法未在超类中定义,则无法从声明为该类型的对象调用该方法。否则就没有意义了 - 如果对象不是子类类型但只有类型超类会怎么样 - 这将是一个类型错误。

如果你不能在超类中实现该方法,那么你要么没有做适当的动态绑定的例子,要么你的超类实际上应该是一个接口或抽象。

例如:

class Animal
{
    void Eat(){
        System.out.println("Yum!");
    }
}

class Dog extends Animal
{
    void Eat(){
        System.out.println("Arf!");
    }
}

现在,如果你写

Animal rex = new Dog();
rex.Eat();

输出将是“Arf!”

但是,如果您将class Dog更改为

class Dog extends Animal
{
    void Eat(){
        System.out.println("Arf!");
    }

    void Bark(){
        System.out.println("Woof!");
    }
}

并写

Animal rex = new Dog();
rex.Bark();

你会收到一个错误 - 动物不会吠叫。事实上,如果雷克斯是一个鱼,它真的没有意义。

答案 1 :(得分:0)

这是预期的行为。

父母 - 例如船 - 对他们的孩子一无所知。您可以拥有数千个不同的类,这些类是Ship的子级。

相关问题