关于在JAVA中将子类转换为超类

3
public class Car {

    String color;

    public void thisIs(){
        System.out.println("Calling method from Car: the color is " + color);
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

public class BMW extends Car {

    public void thisIs(){
        System.out.println("Calling method from BMW: the color is " + color);
    }
    public Car toCar(){
    Car newCar = new Car();
    newCar.setColor(this.color);
    return newCar;
}

}

public class AbstractTest {

    public static void main(String args[]){
        Car aCar = new Car();
        aCar.setColor("Red");
        aCar.thisIs();

        BMW aBMW = new BMW();
        aBMW.setColor("Black");
        aBMW.thisIs();

        //Car aaCar = new Car();
        //aaCar = (Car)aBMW;
        //aaCar.thisIs();

            Car aaCar = aBMW.toCar();
    aaCar.thisIs();
    }
}

我期望的结果是:

从Car类调用方法:颜色为红色

从BMW类调用方法:颜色为黑色

从Car类调用方法:颜色为黑色

但是,我得到的结果是:

从Car类调用方法:颜色为红色

从BMW类调用方法:颜色为黑色

从BMW类调用方法:颜色为黑色

我错在哪里了? 如何使用超类中的方法来获取子类对象中的数据? 我可以在BMW类中编写一个toCar()方法来实现这一点。 但是,为什么强制类型转换不起作用? 提前感谢!

好的!谢谢你!

我知道为什么强制类型转换不起作用了。

因此,我在BMW中添加了一个toCar()方法来获得我想要的结果。


4
这是基本的面向对象编程,你可能需要阅读一本好书。 - Karthik T
我喜欢这个教程的解释方式:http://www.cs.utexas.edu/users/cannata/cs345/Class%20Notes/14%20Java%20Upcasting%20Downcasting.htm - Akavall
是的。链接解释了我误解的内容。谢谢。 - user1947415
5个回答

14

强制类型转换不会改变对象的本质,它仍然是一个 BMW 对象;强制类型转换只是告诉编译器将其视为 Car 对象。

既然我们谈到了继承:没有必要将颜色变量或 getColor()/setColor() 方法同时放在父类和子类中。将它们放在汽车类中意味着它们在任何子类中都可用;在子类中它们是多余且有点令人困惑的。我会完全删除它们。


如果我有一个子类对象,是否有一种方法可以通过超类方法“与该对象交互”?即使子类没有toCar()方法? - user1947415
我不确定你所说的“talk to”具体指什么——超类方法可在所有子类对象上调用,并执行在超类中定义的代码。因此,您可以在BMW上调用setColor()和getColor(),它们的行为与在Car实例或任何其他Car子类的实例上调用时一样(至少是没有重新定义这些方法的任何子类)。这种行为是面向对象设计的根本; BMW是“Car的特殊情况”,因此预期其行为类似于Car加上为BMW定义的任何内容。 - arcy

2
这是因为运行时多态性。即使你有一个指向BMW对象的汽车引用(通过强制转换,你没有修改对象的本质!BMW仍然是BMW,它不会变成Car对象!),最终调用的是BMW的thisIs()方法!这被称为动态方法分派

这是什么?你能再解释一下吗? - user1947415
请了解动态方法分派!并且这样想对象:超类对象是更高的数据类型,而子类对象是较低的数据类型!例如,在基本类型方面,短整型是比整型更低的数据类型。仅仅因为你将一个短整型变量向上转换(扩展)到一个整型,并不意味着短整型变量中的内容会发生改变! - codeMan
谢谢你的回答。但是,我已经理解了多态的概念。我的误解在于类型转换。我曾以为(Car)aBMW的结果会是一个Car对象。但就像Ben Zotto和rcook所说的那样,强制类型转换甚至不能改变对象的本质。 - user1947415

1

即使你把它称作汽车,宝马仍然是宝马。

类型转换并不会改变对象的本质,它只是告诉编译器你打算如何处理它。你创建了一辆宝马,在调用它的thisIs方法时,它仍然是一辆宝马。


0

你不需要将BMW对象显式转换为Car类型,因为BMW对象Car的子类,而Car可以是任何类型(BMW或其他)。所以当你将BMW对象分配给汽车时,编译器会进行隐式转换。在你的情况下,你明确要求编译器将BMW对象强制转换为汽车类型

此外,这种隐式转换并不意味着BMW对象将失去其thisIs()方法或任何其他属性。


-1

考虑以下代码:

public void someMethod(Car c) {
  c.thisIs(); 
}

'c' 可以持有所有子类的引用。无论 'c' 持有哪个引用,都将调用该方法。这也被称为运行时多态性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接