正如我从教科书中学到的,如果我将类型超类的变量名称,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
,但事实并非如此。
答案 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的子级。