2017-08-02 78 views
0

我有以下完全抽象的场景,我尝试使用OOP概念放在一起,但我正在努力如何正确地做到这一点。调用从其超类随机生成的子类的方法

我有3种类型的汽车。这辆车只能做2件事 - 驾驶(1公里)并停下。所有的汽车都可以用同样的方式驱动和停止。所以在OOP的世界里,我代表它的东西,像这样:

class Car{ 
    drive(){...} 
    stop(){...} 
} 

三种类型的汽车是CARA,CARB和CARC,这是该父类汽车的子类。所以让我们来看看它们中的一个,比如CarA,它看起来像这样:

class CarA extends Car{} 

到目前为止,这么好。这是我的任务。我在汽车类型阵列中有大量不同类型的汽车(这是可能的,因为汽车类是所有类型汽车的父母)。我有一个函数可以选出一个随机车(使用一个范围内的随机生成的整数作为索引),称为getRandomCar())。一旦我得到一辆随机车,我的工作就是驾驶汽车(根据汽车父级内定义的功能发生1公里),然后停车。所以,我做这样的事情:

Car car = (Car) getRandomCar(cars); //cars is the Car array with all the different cars 
car.drive(); //car is driven for 1 km 
car.stop(); //car is stopped. 

这工作,因为随机的车,我得到的始终是类型强制转换为它的父类将其存储到名为车一车的参考变量之前。当我打电话给car.drive()时,它会调用Car类的方法drive()。

现在假设其中一辆轿车,比如说CarA,有一种稍微不同的驾驶方式。所以在我的CarA类定义中,我会重载方法drive()。

现在我的问题是,在上面的情况下,如果我得到的随机车之一是CarA型,那么car.drive()调用父方法而不是子方法。但驾驶CarA的方式与其他汽车不同,这就是为什么它具有超载的方法。

因此,在这种情况下,除了在调用car.drive()之前特别设置if条件并检查随机车的类型是否为CarA类型之外,是否有一种很好的方法可以轻松调用CarA的方法(这可能是繁琐的过程,如果说所有的汽车都有自己的驱动方法)。在面向对象的领域中是否有这样一个场景的优秀实现?

+3

你错了,它是'CarA'超载的'drive'方法,即使变量的声明类型只是'Car',也会被调用。但是,如果需要,'CarA'可以使用'super.drive()'从'Car'调用方法 – litelite

+1

阅读关于'Java中的Dynamic Method Dispatch或Runtime Polymorphism'。你声称自己错了* ...如果我得到的一辆随机车是CarA型,那么car.drive()将调用父方法而不是子方法.... *。 –

+0

因此,即使引用变量是父类类型,它是在Java中调用的子类中的重载方法? –

回答

1

在Java中,方法在编译时被检查,但在运行时被绑定。当你声明你的car变量

Car car = (Car) getRandomCar(cars); 

car现在的CarACar引用类型的实例。据编译器可以告诉,car是一个Car

当您拨打car.drive()时,编译器会根据Car类的定义检查该方法。 Car确实包含名为drive()的方法,因此编译成功。当程序实际运行时,JVM会到达该语句并在实际对象上调用drive()。由于car实际上是CarA,因此调用CarA的版本drive()。对于不包含自己定义的CarBCarC,将自动继承Car的版本drive()


其他的一些注意事项(事情,我注意到那是在评论中提到的事情):

  1. 你描述这里的情况被称为重写,不超载。重载是使用相同的名称和返回类型,但参数不同的多个方法。重写是通过在子类中创建一个相同的方法来取代超类的功能。

  2. 在您的car作业中,您不需要转换成Car。由于getRandomCar()可以返回任何类型的Car,它必须是它的返回类型是Carcar也被声明为Car的类型,所以不需要铸造。