我有以下完全抽象的场景,我试图使用OOP概念,但我正在努力解决如何做到这一点。
我有3种类型的汽车。这辆车只能做两件事 - 开车(1公里)然后停下来。所有汽车都可以以相同的方式驱动和停止。因此,在OOP世界中,我将其表示为如此:
class Car{
drive(){...}
stop(){...}
}
这三种类型的汽车是CarA,CarB和CarC,它们都是这个父级Car的子类。所以,让我们选择其中一个,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的Car引用变量之前总是被类型转换为其父类。当我打电话给car.drive()时,它会调用Car class'方法叫做drive()。
现在假设其中一辆汽车,比如CarA,驾驶方式略有不同。因此,在CarA的类定义中,我将重载方法drive()。
现在我的问题是,在上面的场景中,如果我得到的随机车之一是CarA类型,那么car.drive()调用父方法而不是子方法。但是驾驶CarA的方式与其他车型不同,这就是为什么它有一个超负荷的方法。
所以在这种情况下,有一种很好的方法可以轻松调用CarA自己的方法,而不是在调用car.drive()之前专门设置if条件并检查随机车的类型是否为CarA(这可能是一个单调乏味的过程,如果所有汽车都有自己的驱动方法)。在OOP世界中是否有这种情景的良好和优雅的实现?
答案 0 :(得分:1)
在Java中,方法在编译时检查,但在运行时绑定。当您将car
变量声明为
Car car = (Car) getRandomCar(cars);
car
现在是CarA
的实例,其引用类型为Car
。就编译器而言,car
是Car
。
当您调用car.drive()
时,编译器会根据Car
类的定义检查该方法。 Car
确实包含一个名为drive()
的方法,因此编译成功。当程序实际运行时,JVM会到达该语句并在实际对象上调用drive()
。由于car
实际上是CarA
,因此CarA
的{{1}}版本被调用。对于drive()
和CarB
,其中不包含自己的定义,CarC
的{{1}}版本会自动继承。
其他一些注释(我注意到的事情和评论中提到的事情):
您在此处描述的方案称为覆盖,而不是重载。重载使多个方法具有相同的名称和返回类型,但参数不同。覆盖是通过在子类中创建相同的方法来替换超类的功能。
在Car
作业中,您无需投放到drive()
。由于car
可以返回任何类型的Car
,因此它的返回类型必须为getRandomCar()
。 Car
也声明为Car
类型,因此无需投射。