2013-03-27 48 views
32

如何在代碼中使用myAnimal實例調用Animal類的吃喝方法?如何調用超類的重載方法

public class Animal { 
    public void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public void drink() { 
     System.out.println("Animal Drinks"); 
    } 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = myCat;   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

輸出我得到:

Cat Eats 
Cat Drinks 
Cat Eats 
Cat Drinks 

這是我期望的輸出:

Cat Eats 
Cat Drinks 
Animal Eats 
Animal Drinks 
+1

你要撥打的'animal'實施** **無'貓'的實施? – mthmulders 2013-03-27 19:47:57

+4

除非你有'Cat'女巫調用'super.eat();'的方法,否則你不能直接從'Cat' – A4L 2013-03-27 19:51:15

+0

做到這一點你不應該期待你所期望的......不應該在語言定義以及合理或想要的內容。繼承多態的全部意義在於獲得你所看到的,而不是你所期望的。 – 2017-04-07 04:17:27

回答

55

你不能做你想做的。多態性的工作方式是通過做你所看到的。基本上貓總是知道它是一隻貓,並且總是表現得像一隻貓,無論你如何對待貓是貓,貓,貓科,貓科,貓科動物,食肉目,Theria,哺乳動物,脊椎動物,脊索動物,Eumetazoa,動物界,動物,對象,或其他任何東西:-)

+2

你確定。 – 2013-03-27 19:54:35

+1

100%肯定給你想寫的代碼。我會發布另一個答案,可以讓你做你正在做的事情,但它不會是你想做的事情... – TofuBeer 2013-03-27 19:55:33

+0

我投下了反思到這個線程 – WeMakeSoftware 2013-03-27 19:56:15

5

這條線:

Animal myAnimal = myCat;

分配變量myAnimal對象myCat,這你之前創建。因此,當你在此之後調用myAnimal.eat()時,實際上是調用原始myCat對象的方法,該對象輸出Cat Eats

如果要輸出Animal Eats,則必須將Animal實例指定給變量。所以,如果你這樣做,而不是:

Animal myAnimal = new Animal()

變量myAnimal將是Animal一個實例,從而將以前的分配改寫爲Cat

如果你會打電話給在此之後myAnimal.eat(),你實際上調用Animal實例的eat()方法您已經創建,將輸出Animal Eats

結論:你的代碼應該閱讀:

public class Cat extends Animal { 

    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = new Animal();   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 
-1

請不要對這個答案投票......你可以在另外一個投票:-)這是一個不好回答,但顯示你將如何做你正在努力做的事......糟透了。

public class Main 
{ 
    public static void main(final String[] argv) 
    {   
     Child child; 
     Parent parent; 

     child = new Child(); 
     parent = child; 

     child.a(); 
     parent.a(); 
     child.otherA(); 
     parent.otherA(); 
    } 
} 

class Parent 
{ 
    public void a() 
    { 
     System.out.println("Parent.a()"); 
    } 

    public void otherA() 
    { 
     // doesn't matter what goes here... really should be abstract 
    } 
} 

class Child 
    extends Parent 
{ 
    @Override 
    public void a() 
    { 
     System.out.println("Child.a()"); 
    } 

    @Override 
    public void otherA() 
    { 
     super.a(); 
    } 
} 
+3

如果您承認自己是個不好的答案,不應該使用,那麼刪除它可能會更好。 – Rob 2017-04-06 05:48:22

+2

不是真的,它是在那裏向人們展示不該做的事情。任何人都可以想出這個,我想讓人們知道,如果他們這樣做,他們應該把它扔掉。因此,我的請求根本不投票... – TofuBeer 2017-04-06 06:18:37

+5

我認爲如果這是您接受的答案的一部分,會更好。 – 2017-04-07 04:22:50

0

貓不能停止成爲一隻貓,即使它是一隻動物。貓會吃,貓會用貓的方式喝。它可能與動物所做的相似,這就是爲什麼它會覆蓋該方法。如果你想讓它做默認動物,不要重寫。你也許可以做一些奇怪的東西與反思並作出訪問父方法,如不同的方法:

public void superDrink() { 
    Animal.class.getMethod("drink").invoke(); 
} 

但可能是矯枉過正你不覺得嗎?

當然,這可能不會工作,因爲它不是靜態的。

+0

java.lang.NoSuchMethodException – 2015-12-16 13:14:53

16

在這裏,你將有一個選項,選擇你要調用的方法。

public class Cat extends Animal { 

    public void superEat() { 
     super.eat(); 
    } 

    public void superDrink() { 
     super.drink(); 
    } 

    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 
} 
1

如果您在每類中的方法靜態的,它應該工作。

public class Animal { 
    public static void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public static void drink() { 
     System.out.println("Animal Drinks"); 
    } 
} 


public class Cat extends Animal { 
    @Override 
    public static void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public static void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = myCat;   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

上面的代碼將提供以下輸出

Cat Eats 
Cat Drinks 
Animal Eats 
Animal Drinks 
+4

我不認爲這是OP所要求的,他希望能夠訪問實例化對象中的重寫方法,我會去做其他事情,如重新設計對象,如果這是他是需要的。 – Goodwine 2014-05-15 00:02:45

2

您可以創建類動物的構造,即另需馬斯作爲參數,並創建新的實例基礎上提供一個。

public class Animal { 
    //some common animal's properties 
    private int weight; 
    private int age; 

    public Animal() { 
     // empty. 
    } 

    public Animal(final Animal otherAnimal) { 
     this.weight = otherAnimal.getWeight(); 
     this.age = otherAnimal.getAge(); 
    } 

    public void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public void drink() { 
     System.out.println("Animal Drinks"); 
    } 

    // setters and getters. 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     // note: myAnimal is not a Cat, it's just an Animal. 
     Animal myAnimal = new Animal(myCat);   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 
+1

這在C++中被稱爲「切片」;你「切片」一隻貓的母體部分,產生一隻不再是貓的動物。它發生在C++中,使用與OP的語法相似的語法。在Java中,你必須明確地做到這一點。請注意,這是一個改進,意外切片真的很糟糕。 – Yakk 2017-04-10 13:10:10

2
  • 訪問靜態字段,實例字段和靜態方法依賴於類參考變量不實際的對象到的變量指向的。
  • 請記住,成員變量是被映射的,沒有被覆蓋。
  • 這與在實例方法中發生的情況相反。
    在實例方法的情況下,調用對象的實際類別的方法。

    class ABCD { 
        int x = 10; 
        static int y = 20; 
    
        public String getName() { 
         return "ABCD"; 
        } 
    } 
    
    class MNOP extends ABCD { 
        int x = 30; 
        static int y = 40; 
    
        public String getName() { 
         return "MNOP"; 
        } 
    } 
    
    public static void main(String[] args) { 
    
        System.out.println(new MNOP().x + ", " + new MNOP().y); 
    
        ABCD a = new MNOP(); 
        System.out.println(a.x); // 10 
        System.out.println(a.y); // 20 
        System.out.println(a.getName()); // MNOP 
    } 
    

在本例中雖然對象myCat被分配​​給一個動物對象的引用,(Animal myAnimal = myCat)實際的對象是Cat類型的,並且它的行爲,因爲它是貓。

希望這會有所幫助。

0

幾點建議:

  1. 子類的引用不要傳遞給超類和除超類方法被調用的重寫的方法。從超類實例中調用超類方法。

    Animal myAnimal = new Animal(); 
    myAnimal.eat(); 
    
  2. 如果你想從調用子類的超類的方法,顯式調用父類方法的名稱與super.methodName();

    public void eat() { 
        super.eat(); 
        System.out.println("Cat Eats"); 
    } 
    
  3. 請勿在子類中重寫超類方法。總是調用超類方法。
0
public class Main { 
    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = new Animal(); 
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

public class Animal { 
    public void eat(){ 
     System.out.println("Animal eat() called"); 
    } 
    public void drink(){ 
     System.out.println("Animal drink() called"); 
    } 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat eat() called"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("cat drink() called"); 
    } 
} 

OUTPUT:

貓吃()稱爲

貓飲料()稱爲

動物吃的()稱爲

動物飲料()稱爲

您需要創建超類Animal的對象或另一種選擇是使用關鍵字super在子類中的方法如super.eat()super.drink()