2013-03-27 3 views
32

Как я могу назвать метод eat and drink класса Animal с экземпляром myAnimal в коде?Как вызвать переопределенный метод суперкласса

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' реализации ** без ** реализация 'cat'? – mthmulders

+4

Если у вас нет метода в 'Cat', ведьма вызывает' super.eat(); 'вы не можете сделать это непосредственно из' Cat' – A4L

+0

. Вы не должны ожидать, что ожидаете ... не должны оба с точки зрения определение языка и с точки зрения разумного или желательного желания. Весь смысл полиморфизма наследования заключается в том, чтобы получить то, что вы видите, а не то, что, как вы говорите, ожидаете. –

ответ

55

Вы не можете делать то, что вы хотите. Способ полиморфизма работает, делая то, что вы видите.

В основном кошка всегда знает, что это кошка, и всегда будет вести себя как кошка, независимо от того, лечишь ли ты, как кошка, фелис, фелины, фелиды, фелидома, карнивора, териа, млекопитающие, вертебрата, хордата, эуметазоа, Animalia, животное, объект, или что-нибудь еще :-)

+2

Вы уверены в этом. –

+1

100% уверен, что код, который вы хотите написать. Я отправлю еще один ответ, который позволит вам делать то, что вы пытаетесь сделать, но это будет не то, что вы хотите сделать ... – TofuBeer

+0

Я снял отражение в этой теме – WeMakeSoftware

5

Эта линия:

Animal myAnimal = myCat;

присваивает переменной myAnimal к объекту myCat, который вы создали ранее. Поэтому, когда вы вызываете myAnimal.eat() после этого, вы на самом деле вызываете метод исходного объекта myCat, который выводит Cat Eats.

Если вы хотите вывести Animal Eats, вам нужно назначить экземпляр Animal переменной. Так что, если вы могли бы сделать это вместо:

Animal myAnimal = new Animal()

переменная myAnimal будет экземпляром Animal, и, таким образом, будет перезаписывать предыдущее задание Cat.

Если вы будете называть myAnimal.eat() после этого, вы на самом деле вызова eat() метода экземпляра Animal вы создали, который будет выводить 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

+2

Не совсем, здесь есть люди, чтобы не делать. Любой может придумать это, я хотел сообщить людям, что если бы они это сделали, они должны были выбросить его. Поэтому моя просьба не голосовать на нем вообще ... – TofuBeer

+5

Я думаю, было бы лучше, если бы это был раздел вашего принятого ответа. –

0

Кошка не может перестать быть кошкой, даже если это животное. Кошка будет есть, а кошка будет пить кошачьим способом. Это может быть похоже на то, что делает Animal, поэтому он переопределяет метод. Если вы хотите, чтобы он делал то, что делает животное по умолчанию, не переопределяйте. Вы могли бы сделать некоторые странные вещи с отражением и сделать отдельные методы, которые имеют доступ родительские методы, такие как:

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

, но что может быть избыточна вы не думаете?

Конечно, возможно, это не сработало, так как оно не является статичным.

+0

java.lang.NoSuchMethodException –

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

Я не думаю, что это то, о чем просит ОП, он хочет иметь доступ к переопределенному методу в экземпляре объекта, я бы пошел на что-то еще, например, перепроектировать объекты, если это то, что он требуется. – Goodwine

2

Вы можете создать конструктор для класса 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(); 
    } 
} 
+1

Это называется «нарезкой» на C++; вы «нарезаете» родительскую часть кота, чтобы создать животное, которое больше не является кошкой. Это происходит в C++, используя синтаксис, аналогичный синтаксису OP. В Java вы должны делать это явно. Обратите внимание, что это улучшение, случайная нарезка действительно отстойная. – Yakk

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 (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. Не переопределяйте метод суперкласса в классе child. Вызывается метод супер класса.
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"); 
    } 
} 

ВЫВОД:

Кошка ест() называется

кошка пить() называется

Животное едят() называется

животных пить() называется

Вы должны создать объект класса супер Animal или другой вариант заключается в использовании ключевого слова super в методах класса ребенка, например, super.eat() или super.drink()