web-dev-qa-db-ja.com

スーパークラスのオーバーライドされたメソッドを呼び出す方法は?

コード内のAnimalインスタンスでmyAnimalクラスのeat and drinkメソッドを呼び出すにはどうすればよいですか?

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
42
Hisham Muneer

あなたがしたいことはできません。ポリモーフィズムが機能する方法は、あなたが見ていることをすることです。

基本的に、猫は猫であることを常に知っており、猫、Felis、Felinae、Felidae、Feliformia、Carnivora、Theria、Mammalia、Vertebrata、Chordata、Eumetazoa、Animalia、Animal、オブジェクト、またはその他:-)

65
TofuBeer

ここで、呼び出すメソッドを選択するオプションがあります。

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

この行:

_Animal myAnimal = myCat;_

変数myAnimalを、以前に作成したオブジェクトmyCatに割り当てます。したがって、その後myAnimal.eat()を呼び出すと、実際には_Cat Eats_を出力する元のmyCatオブジェクトのメソッドを呼び出しています。

_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();
    }
}
_
6
Piet van Dongen
  • 静的フィールド、インスタンスフィールド、および静的メソッドへのアクセスは、変数が指す参照変数のクラスおよび実際のオブジェクトではないに依存します。
  • メンバー変数は上書きされず、シャドウされることに注意してください。
  • これは、インスタンスメソッドの場合に起こることの反対です。
    インスタンスメソッドの場合、オブジェクトの実際のクラスのメソッドが呼び出されます。

    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オブジェクト参照に割り当てられていますが、(Animal myAnimal = myCat)ActualオブジェクトはCat型であり、猫のように動作します。

お役に立てれば。

3
tharindu_DG

各クラスのメソッドを静的にすると、動作するはずです。

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
2
Vbee

クラス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();
    }
}
2
friednail

いくつかの提案:

  1. 子クラス参照をスーパークラスに渡さないでください。ただし、オーバーライドされたメソッドに対してスーパークラスメソッドを呼び出す必要がある場合を除きます。スーパークラスインスタンスからスーパークラスメソッドを呼び出します。

    Animal myAnimal = new Animal();
    myAnimal.eat();
    
  2. 子クラスからスーパークラスメソッドを呼び出す場合は、super.methodName()を使用してスーパークラスメソッド名を明示的に呼び出します。

    public void eat() {
        super.eat();
        System.out.println("Cat Eats");
    }
    
  3. 子クラスのスーパークラスメソッドをオーバーライドしないでください。常にスーパークラスメソッドが呼び出されます。
1
Ravindra babu

この答えには投票しないでください...他の答えには投票できます:-)これは悪い答えですが、あなたがしようとしていることをどうやって行うかを示しています...貧弱です。

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

たとえ猫であっても、猫は猫であることをやめられません。猫は猫のように食べ、猫は飲みます。それは動物がすることと似ているかもしれません。それがメソッドをオーバーライドする理由です。動物がデフォルトで行うことを実行する場合は、オーバーライドしないでください。おそらくリフレクションを使用して奇妙なことを行い、次のような親メソッドにアクセスする別のメソッドを作成できます。

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

しかし、それはやり過ぎかもしれませんね。

もちろん、静的ではないため、おそらく動作しません。

0
Jimi Kimble