2013-04-03 160 views
0
class Test { 
    public static void main(String[] args) { 
     Animal a = new Dog(); 
     Dog d = new Dog(); 

     d.makeNoise(); // output "Sub" 
     a.makeNoise(); // output "Sub" then what is use of calling this. why not call d.makeNoise() only. 

    } 
} 

abstract class Animal { 
    public void makeNoise() { 
     System.out.println("Super"); 
    } 
} 

class Dog extends Animal { 
    @Override 
    public void makeNoise() { 
     System.out.println("Sub"); 
    } 
} 

我們必須在這個話題15分鐘討論(15分鐘太長我猜的)我解釋面試官如何動態多態性會隨着a.makeNoise();的幫助下可以實現,但她仍是說兩者都給予相同的輸出。
a.makeNoise();輸出「Sub」然後調用這個有什麼用處。爲什麼不叫d.makeNoise()只有
我去了接口,但仍然問題是如果子類引用給出相同的輸出,那麼爲什麼要使用超類的引用。
動態多態性

訪員問題是,a.makeNoise();有什麼區別?爲什麼不只在兩個輸出相同的情況下才撥打d.makeNoise();

可能的正確答案是什麼?

+0

可能的正確答案是什麼問題? – NPE

+0

究竟是什麼問題? – benzonico

+0

答案似乎是你不懂多態! – John3136

回答

2
Animal a = new Dog(); // this animal is a dog 
Dog d = new Dog();  // this dog is a dog 

狗是一隻狗,但是你宣佈它。

a.getClass()等於d.getClass()等於Dog.class

在另一方面:

Animal a = new Animal(); // this animal is an animal 
a.makeNoise();   // prints "Super" 
+0

我回答同樣的問題,但面試官期待別的。它以前如何? – AmitG

+3

@AmitG Schweppes? – sp00m

1

這是reason-

Animal a = new Dog(); 

動物是狗這樣的噪音將是相同的:)

如果創建另一種動物,貓說,與該方法,並指向動物貓,你應該得到不同的噪音。

+0

我回答同樣的問題,但面試官期待別的。 – AmitG

+0

也許你應該嘗試一個接口。其他採訪者必須期望該方法在Animal類中是抽象的。 –

+0

我去了接口,但仍然問題是如果子類引用給出相同的輸出,那麼爲什麼要使用超類參考 – AmitG

2

下面的例子說明了動態多態性。 a和d都被宣佈爲動物,但d實際上是一隻狗。

請注意,當我在動物d上調用makeNoise時,java會知道d實際上是一隻狗,而不是任何動物。

class Test { 
    public static void main(String[] args) { 
     Animal a = new Animal(); 
     Animal d = new Dog(); 

     d.makeNoise(); // output "Bark" - d is an animal that barks 
     a.makeNoise(); // output "Squawk" - a is an animal that squawks 

    } 
} 

class Animal { 
    public void makeNoise() { 
     System.out.println("Squawk"); 
    } 
} 

class Dog extends Animal { 
    @Override 
    public void makeNoise() { 
     System.out.println("Bark"); 
    } 
} 
+0

我回答同樣的問題,但面試官期待別的。它以前如何? – AmitG

+1

這和你的答案不一樣。仔細看看a和d的聲明。我的例子實際上會給出不同的輸出。 –

+0

我明白了。但是我說我改變了方式,改變了代碼並解釋了整個事情,但她期待別的事情。我已經注意到你改變了'Animal a = new Animal();' – AmitG

1

您簡單的例子不存在的情況不夠好。

Collection<Animal> caged = getCagedAnimals(); 
for (Animal a : caged) 
    a.makeNoise(); 

由於動物(類)有很多種類,每種都會產生不同的噪音。可以這麼說,我們不需要任何類型轉換來獲得不同的行爲。想象一下慘狀這會發生,如果我們希望每個動物發出聲響沒有多態性:

for (Animal a : caged) { 
    if (a instanceof Dog) 
    ((Dog)a).woof(); // or, ((Dog)a).makeNoise() 
    else if (a instanceof Cat) 
    ((Cat)a).meow(); // or, ((Cat)a).makeNoise() 
    else {...} 
} 

讓我們有類型T的對象我們正試圖調用的toString()如下(實際上,使用虛擬方法表)(由Object類中定義) 動態方法調用進行:

C = T 
do 
    if (C defines toString()) { 
    call T.toString() 
    break 
    } 
    C = superclass of C 
while (C != null) 
throw new NoSuchMethodError(); 

現在,如果我們有

Object obj = new T(); 

我們稱之爲

obj.toString(); 

我們實際上是調用類T的的toString()

+0

我也解釋了這個例子,但面試官期待別的。它以前如何? – AmitG

0
class Account { 
    public static void main(String[] args) { 
     Animal a = new Dog(); 
     Dog d = new Dog(); 
     d.makeNoise(); 
     a.makeNoise(); 
     a = new Cat(); 
     a.makeNoise(); 
    } 
} 

abstract class Animal { 
    public void makeNoise() { 
     System.out.println("Super"); 
    } 
} 

class Dog extends Animal { 
    public void makeNoise() { 
     System.out.println("Sub"); 
    } 
} 

class Cat extends Animal { 

} 

看到上面的修改例和意見

  1. 我們有一個抽象類,動物與makeNoise實現(讓我在這裏說的默認實現)
  2. 我們有一個狗類,這是一種動物但有一個定製的makeNoise方法
  3. 我們有一個Cat類,它是Type動物的,​​但沒有定製的makeNoise方法。它使用動物類型的默認makeNoise。
  4. 如果我使用Animal a = new Dog()和a.makeNoise(),那麼只要我希望不更改任何其他類,就可以從Dog類中刪除我的makenoise方法。它仍然會編譯並執行,沒有任何錯誤。
  5. 如果我使用Dog d = new Dog()和d.makeNoise(),那麼我無法隨時從Dog類中刪除我的makenoise方法。如果我這樣做,我還需要更改應用程序的主類來編譯。
+0

@AmitG我看到你編輯了上面的答案,但沒有評論這是否有用 – Joe2013

0

我會給一個普通的前: - personA有一個銀行帳戶,他擁有該帳戶(提取,存款,loanetc)的所有權限。 personB想要在此時間將資金存入personA賬戶,他想訪問personA的賬戶,但我們只需提供存款權限。

class perosnB 
{ 
public void deposit() 
{ 
................ 
} 
} 
class personA extends personB 
{ 
public void deposit() 
{ 
...... 
} 
public void withdraw() 
{ 
...... 
} 
} 
personA p=new personB(); 
PersonB p2=new personB(); 

通過使用p對象我們只能訪問提取方法。通過使用p2我們也可以訪問存款。 天氣personA類是抽象的還是不抽象的。如果personA是personA類的抽象類創建對象是不可能的(personA p = new personA())。 personA p = new personB()是可能的。

+0

你可能想編輯你的答案。 'personA p = new personB();'編譯時錯誤。我對這個問題有你的想法。我也回答了這個概念(只有不同​​例子的概念)。 – AmitG

0
Animal a = new Dog(); 

一個是類型動物的一個參考,但它是指型狗的對象。

這裏覆蓋makeNoise()動物類的方法。

class Animal { 
    public void makeNoise() { 
     System.out.println("Squawk"); 
    } 
} 

class Dog extends Animal { 
    @Override 
    public void makeNoise() { 
     System.out.println("Bark"); 
    } 
} 

由於對象是狗 JVM的將結合makeNoise()方法到對象,並結合將在運行時進行。

所以

a.makeNoise(); 

輸出將是

1

考慮有3類

  1. 動物
  2. 貓 貓和狗是動物的子類。

class Test { 
 
    public static void main(String[] args) { 
 
     Animal a = new Animal(); 
 
     
 
    int user_input=userinput(); //returns 1 for cat and 2for dog 
 
    switch(user_input) 
 
    { 
 
    case 1:Animal d=new Cat(); 
 
    break; 
 
    case 2: Animal d=new Dog(); 
 
    break; 
 
    } 
 
     d.makeNoise(); // output "Bark"/"meow" as per user input(dynamic linking) 
 
     a.makeNoise(); // output "Squawk" - a is an animal that squawks 
 
    } 
 
    } 
 
    class Animal { 
 
    public void makeNoise() { 
 
     System.out.println("Squawk"); 
 
    } 
 
    } 
 
    class Cat extends Animal { 
 
    @Override 
 
    public void makeNoise() { 
 
     System.out.println("meow"); 
 
    } 
 
    } 
 
    class Dog extends Animal { 
 
    @Override 
 
    public void makeNoise() { 
 
     System.out.println("Bark"); 
 
    } 
 
    }