簡體   English   中英

如何調用超類的重寫方法?

[英]How to call the overridden method of a superclass?

如何在代碼中用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

你不能做你想做的事。 多態性的工作方式是做你所看到的。

基本上,貓總是知道它是一只貓,並且無論您是否將其視為貓,貓科動物,貓科動物,貓科動物,貓形目,食肉動物,Theria,哺乳動物,脊椎動物,脊索動物,Eumetazoa,動物界,動物,對象,或其他任何東西:-)

在這里,您可以選擇要調用的方法:

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");
    }
}

這一行:

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();
    }
}
  • 對靜態字段、實例字段和靜態方法的訪問取決於引用變量的類,不是變量指向的實際對象
  • 請記住,成員變量是隱藏的,而不是覆蓋的。
  • 這與實例方法的情況相反。
    在實例方法的情況下,調用對象的實際類的方法。

     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(ax); // 10 System.out.println(ay); // 20 System.out.println(a.getName()); // MNOP }

在此示例中,盡管對象 myCat 被分配給 Animal 對象引用( Animal myAnimal = myCat ),但 Actual 對象是Cat類型,它的行為就像一只貓。

希望這可以幫助。

您可以為類 Animal 創建構造函數,該構造函數將另一個Animas 作為參數,並基於提供的一個創建新實例。

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();
    }
}

如果您將每個類中的方法設為靜態,它應該可以工作。

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

幾點建議:

  1. 不要將子類引用傳遞給超類,並且必須為重寫的方法調用超類方法之外的方法。 從超類實例調用超類方法。

     Animal myAnimal = new Animal(); myAnimal.eat();
  2. 如果要從子類調用超類方法,使用 super.methodName() 顯式調用超類方法名;

     public void eat() { super.eat(); System.out.println("Cat Eats"); }
  3. 不要覆蓋子類中的超類方法。 總是調用超類方法。

你可以使用 super 關鍵字實現你想要的,它允許訪問被覆蓋的方法。

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

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

 public class Cat extends Animal {

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

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

   public void printMessage(){
     super.eat();
     super.drink();
   }

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

請不要對這個答案投票......你可以對另一個投票:-) 這是一個糟糕的答案,但顯示了你將如何做你想做的事情......糟糕。

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();
    }
}

貓不能停止成為貓,即使它是動物。 貓會吃貓會喝貓的方式。 它可能類似於 Animal 所做的事情,這就是它覆蓋該方法的原因。 如果你想讓它做動物默認做的事情,不要覆蓋。 您可能可以通過反射做一些奇怪的事情,並制作訪問父方法的單獨方法,例如:

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

但這可能有點矯枉過正,你不覺得嗎?

當然,這可能行不通,因為它不是靜態的。

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");
    }
}

輸出:

貓吃()調用

貓喝()調用

動物吃()調用

動物飲料()調用

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

您可以通過對代碼進行一些小的更改來做您想做的事情。 自然地,Animal 類的方法已被覆蓋,您不能簡單地通過更改引用類型來訪問它們。 相反,你可以稍微改變一下 eat 和 Drink 函數的定義,如下所示。

class Animal{
    public void eat(boolean randomBoolean){
        System.out.println("Animal eats");
    }
    public void drink(boolean randomBoolean){
        System.out.println("Animal drinks");
    }
}

class Cat extends Animal{
    public void eat(boolean wantOverriden){
        if(wantOverriden){
            boolean randomBooleanValue=true|false;
            super.eat(randomBooleanValue);
        }
        else{
            System.out.println("Cat eats");
        }
    }
    public void drink(boolean wantOverriden){
        if(wantOverriden){
            boolean randomBooleanValue=true|false;
            super.drink(randomBooleanValue);
        }
        else{
            System.out.println("Cat drinks");
        }
    }
}

現在您應該能夠通過 Cat 類對象訪問 Animal 類的覆蓋方法,只需傳入一個布爾值來指示您是否要這樣做,例如:

Cat c=new Cat();
c.eat(false);     //Indicating that you dont want to access the overriden method
c.drink(false);   //Indicating that you dont want to access the overriden method
c.eat(true);          //Indicating that you want to access the overriden method
c.drink(true);        //Indicating that you want to access the overriden method

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM