2017-08-02 111 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的類型,所以不需要鑄造。