2012-02-20 62 views
0

我是OOP的新手,所以我有一個愚蠢的問題,關於什麼時候上課extendsOOP Java:可以將子類返回給父類嗎?

這裏我舉的例子:

public class Test { 
    public Monitor getMonitor(){ 
     return new LCD(); 
    } 

    class LCD extends Monitor { NO-ERROR 
    class LCD {     ERROR at line `return new LCD` 
     //some other method or function not in Monitor Class. Example: 
     boolean isSamsung; 
     public LCD whatkindLCD(){   
     }  
    } 
} 

我對上面的代碼中有一個問題:因爲LCDMonitor擴展和LCD具有一些其他性能/方法監測沒有。所以,LCDMonitor的孩子吧?

這意味着你試着把一個「大盒子」放到一個「小盒子」中。那麼,爲什麼當我return new LCD,Eclipse沒有注意到錯誤,因爲當我只使用class LCD {

謝謝:)

+0

什麼是錯誤信息? – 2012-02-20 17:12:42

+0

不,嘗試投擲,當你拿回顯示器。 – 2012-02-20 17:13:27

+2

@TedHopp在Eclipse中,它會注意到:'不能從LCD轉換爲顯示器類' – hqt 2012-02-20 17:14:48

回答

1

將繼承理解爲「是」的關係。這裏有一個簡單的例子,我用它來理解我在新手年代的繼承。

class Employee 
{ 
    String name; 
    int salary; 

    Employee() 
    { 
     name = "Employee"; 
     salary = 5000; 
    } 
    public String getName() 
    { 
     return name; 
    } 
    public int getSalary() 
    { 
     return salary; 
    } 
} 
class Manager extends Employee 
{ 
    int bonus; 
    int salary; 

    Manager() 
    { 
     bonus = 1000; 
     salary = 6000; 
    } 
    public int getBonus() 
    { 
     return bonus; 
    } 
    public int getSalary() 
    { 
     return salary; 
    } 
} 

class Test 
{   
    public static void main(String[] args) 
    { 
     Employee e = new Employee(); 
     System.out.println(e.getName()); 
     //System.out.println(e.getBonus()); 
     System.out.println(e.getSalary()); 

     System.out.println(); 

     Manager m = new Manager(); 
     System.out.println(m.getName()); 
     System.out.println(m.getBonus()); 
     System.out.println(m.getSalary()); 

     System.out.println(); 

     Employee em = new Manager(); 
     System.out.println(em.getName());     
     //System.out.println(em.getBonus());    
     System.out.println(((Manager)em).getBonus()); 
     System.out.println(em.getSalary());  
     } 
} 

編譯器在調用任何操作之前查找引用類型。 em.getBonus()不起作用,因爲Employee沒有獎勵方法。 但使用一個演員,我們可以使其工作。 ((經理)EM)getBonus()

之所以編譯器查找引用類型調用任何操作上它是如下之前:

管理器[]管理者=新管理器[10];

是合法的這個數組轉換爲一個Employee []數組:

僱員[]人員=管理人員; //好的

當然,爲什麼不呢,你可能會想。畢竟,如果經理[我]是經理,那麼他也是一名員工。但事實上,令人驚訝的事情正在發生。請記住,經理和員工都是對同一陣列的引用。

現在考慮的聲明

人員[0] =新僱員( 「約翰Eipe」,...);

編譯器會高興地允許這個任務。 但員工[0]和經理[0]是相同的參考,所以看起來我們設法將僅僅一名員工偷運到管理層 的行列中。

這將是非常糟糕的 - 調用管理器[0] .setBonus(1000)將嘗試訪問不存在的實例字段並會破壞鄰近的內存。 爲了確保不會發生此類損壞,所有陣列都記住它們創建時的元素類型 ,並且它們監視只有兼容的引用存儲在它們中的 。例如,作爲新Manager [10]創建的陣列會記住它是一個由 管理器組成的數組。嘗試存儲Employee參考會導致ArrayStoreException。

+1

非常清晰的例子和解釋。正如你所說的那樣:在新手年期間:D因此,作爲例子,我明白:當你給別人打電話是一名僱員時(但實際上是一名經理),編譯器會阻止你將僱員當作經理,除非你'typecast':「這名員工必須是經理,對:D – hqt 2012-02-21 06:52:37

3

盒類比是錯誤的,想到的is a關係來代替。

在第一個示例中,LCD extends MonitorLCD is a Monitor,因此在任何需要Monitor的地方,LCD都可以。當你用真實的術語思考而不是看代碼時,你意識到這是正確的。一般你可以期待一臺顯示器的任何東西(例如顯示一張圖片),一臺液晶顯示器就可以。

在第二個示例中,LCD不是顯示器,因此您會收到錯誤消息。

+2

正如我對Doyle所說的,我只是不知道是:爲什麼可以將'LCD'分配爲'Monitor',因爲'LCD'有一些「Monitor」沒有的屬性。在正常的生活中,你可以說'LCD'是一個'Monitor'。但我無法想象,爲什麼你可以像'LCD'變量那樣使用'Monitor'變量? – hqt 2012-02-20 17:19:28

+2

是的,但這些屬性並不重要。如果有人要求喝一杯水,他們通常不會在意玻璃是用塑料,玻璃或金屬製成的,不管它是否有手柄,或者如果是杯子,是什麼樣的裝飾,如果有的話具有。不,唯一重要的是它可以容納水,並且水可以從中喝掉。在這裏也是如此:通過定義你的方法來返回一個'Monitor'類型,你聲明你根本沒有對它可能具有的任何附加屬性感興趣。 – biziclop 2012-02-20 17:22:35

+2

啊。謝謝。所以,你的意思是,當有人問:「給我一杯水」。你可以給他一個金屬玻璃或塑料玻璃,對吧? – hqt 2012-02-20 17:26:14

5

在您的第二個(錯誤)情況下,您忘記聲明LCD實際上確實延伸了Monitor。你只是定義一個「正常」,獨立的類 - 所以new LCD()而不是Monitor的一個實例。

編譯器應該是快樂的,如果你聲明LCD類是這樣的:

class LCD extends Monitor { 
    //some other method or function not in Monitor Class. Example: 
    boolean isSamsung; 
    public LCD whatkindLCD(){   
    }  
} 

編輯(在響應評論):這不是一個問題,在所有的LCD類有額外屬性/方法相比Monitor。代碼將被稱爲getMonitor(),只是真的關心它得到了Monitor回來 - 也就是說,它具有Monitor的所有方法和屬性以及行爲。

所以,如果你對你的MonitorturnOffdisplayBitmap(int[][] data)方法,那麼你的LCD類也將有這些方法。當需要時,LCD的任何實例都可以表現爲Monitor - 這是OO語言中子類化的基本原理。因此,無論何時需要某個Monitor,您可以給它一個LCDCRTSamsungLCD的實例,而如果您有這些,並且編譯器可以確信正確的方法/屬性將存在並且可以被調用。

(從技術上講這是Liskov substitution principle如果你喜歡正式的定義,但你並不需要了解它的詳細程度。)

+2

是的。我知道爲什麼'class LCD'會出錯。我不知道的是:爲什麼可以將'LCD'分配爲'Monitor',因爲'LCD'有一些屬性,'Monitor'不是 – hqt 2012-02-20 17:17:47

+3

哦。感謝您的鏈接給我。我無法想象這種簡單的想法背後有一個原則。太有趣了 ! – hqt 2012-02-21 14:42:17

0

你的方法getMonitor返回「監控」型。

當您使用顯示器擴展您的班級LCD時,您所說的編譯器即LCD 顯示器。 當您刪除擴展時,LCD類變成普通類而不是監視器類型。 如果您將getMonitor修改爲

public LCD getMonitor(){ 
     // code here 
} 

錯誤會消失。