Qu'est-ce que la méthode se cache en Java? Même l'explication JavaDoc est déroutante


Javadoc dit:

La version de la méthode cachée qui est invoquée est celle de la superclasse, et la version de la méthode remplacée qui est invoquée est celle de la sous-classe.

Ne me dit rien. Tout exemple clair montrant la signification de cela sera très apprécié.

Author: Senthil Kumaran, 2013-05-01

5 answers

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

public class Cat extends Animal {
    public static void foo() {  // hides Animal.foo()
        System.out.println("Cat");
    }
}

Ici Cat.foo() est dit pour masquer Animal.foo(). Le masquage ne fonctionne pas comme le remplacement, car les méthodes statiques ne sont pas polymorphes. Donc, ce qui suit se produira:

Animal.foo(); // prints Animal
Cat.foo(); // prints Cat

Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;

a.foo(); // should not be done. Prints Animal because the declared type of a is Animal
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat
d.foo(); // should not be done. Prints Animal because the declared type of d is Animal

Appeler des méthodes statiques sur des instances plutôt que des classes est une très mauvaise pratique, et ne devrait jamais être fait.

Comparez cela avec les méthodes d'instance, qui sont polymorphes et sont donc remplacées. La méthode appelée dépend du type d'exécution concret de l'objet:

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

public class Cat extends Animal {
    public void foo() { // overrides Animal.foo()
        System.out.println("Cat");
    }
}

Alors ce qui suit sera arrive:

Animal a = new Animal();
Animal b = new Cat();
Animal c = new Cat();
Animal d = null;

a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException
 112
Author: JB Nizet, 2018-06-14 13:13:05

Tout d'abord, qu'entend-on par masquage de méthode?

Masquage de méthode signifie que la sous-classe a défini une méthode de classe avec la même signature qu'une méthode de classe dans la superclasse. Dans ce cas, la méthode de superclasse est masquée par la sous-classe. Cela signifie que: La version d'une méthode exécutée ne sera PAS déterminée par l'objet utilisé pour l'invoquer. En fait, il sera déterminé par le type de référence variable utilisée pour appeler la méthode.

Qu'entend-on par méthode prépondérante?

La substitution de la méthode

Signifie que la sous-classe avait défini une méthode d'instance avec la même signature et le même type de retour( y compris le type covariant) que la méthode d'instance dans la superclasse. Dans ce cas, la méthode de la superclasse est remplacée par la sous-classe. Cela signifie que: La version de la méthode exécutée sera déterminée par l'objet qui est utilisé pour l'invoquer. Il ne sera pas déterminé par le type de variable de référence utilisée pour invoquer la méthode.

Pourquoi les méthodes statiques ne peuvent-elles pas être remplacées?

Parce que les méthodes statiques sont résolues statiquement (c'est-à-dire au moment de la compilation) en fonction de la classe sur laquelle elles sont appelées et non dynamiquement comme dans le cas des méthodes d'instance qui sont résolues polymorphiquement en fonction du type d'exécution de l'objet.

Comment devrait méthodes statiques être consulté?

Les méthodes statiques doivent être accessibles de manière statique. c'est à dire par le nom de la classe elle-même plutôt que d'utiliser un exemple.

Voici la courte démo pour la méthode de remplacement et de masquage:

class Super
{
  public static void foo(){System.out.println("I am foo in Super");}
  public void bar(){System.out.println("I am bar in Super");}
}
class Child extends Super
{
  public static void foo(){System.out.println("I am foo in Child");}//Hiding
  public void bar(){System.out.println("I am bar in Child");}//Overriding
  public static void main(String[] args)
  {
     Super sup = new Child();//Child object is reference by the variable of type Super
     Child child = new Child();//Child object is referenced by the variable of type Child
     sup.foo();//It will call the method of Super.
     child.foo();//It will call the method of Child.

     sup.bar();//It will call the method of Child.
     child.bar();//It will call the method of Child again.
  }
}

Sortie est

I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child

Clairement, comme spécifié, puisque foo est la méthode de classe, la version de foo invoquée sera déterminée par le type de variable de référence (c'est-à-dire Super ou Child) référençant l'objet de Child. Si il est référencé par Super variable foo de Super est appelé. Et s'il est référencé par Child variable foo de Child est appelé.
alors que,
Puisque bar est la méthode d'instance, la version de bar invoquée est uniquement déterminée par l'objet(c'est-à-dire Child) qui est utilisé pour l'invoquer. Peu importe par qui référence de variable (Super ou Child, elle est appelée , la méthode qui va être appelé est toujours de Child.

 32
Author: Vishal K, 2015-09-13 20:57:06

À écraser une méthode signifie que chaque fois que la méthode est appelée sur un objet de la classe dérivée, la nouvelle implémentation sera appelée.

À masquer une méthode signifie qu'un appel non qualifié à ce nom dans la portée de cette classe (c'est-à-dire dans le corps de l'une de ses méthodes, ou lorsqu'il est qualifié avec le nom de cette classe) appellera maintenant une fonction complètement différente, nécessitant une qualification pour accéder à la classe .

Plus de description Héritage Java: Méthodes écrasées ou cachées

 3
Author: ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, 2017-05-23 10:31:31

Si une sous-classe définit une méthode de classe avec la même signature qu'une méthode de classe dans la super-classe, la méthode dans la sous-classe se cache l'un dans la superclasse.

Les méthodes cachées sont dans un contexte statique, je crois. Les méthodes statiques ne sont pas remplacées, en soi, car la résolution des appels de méthode effectués par le compilateur au moment de la compilation lui-même. Donc, si vous définissez une méthode statique dans la classe de base avec la même signature que celle présente dans la classe parente, alors la méthode dans la sous-classe se cache la méthode héritée de la super classe.

class Foo {
  public static void method() {
     System.out.println("in Foo");
  }
}

class Bar extends Foo {
   public static void method() {
    System.out.println("in Bar");
  }
}
 2
Author: NINCOMPOOP, 2013-05-01 06:32:23

, Par exemple, vous pouvez remplacer les méthodes d'instance dans une super classe mais pas statique.

Cacher est Parent de la classe possède une méthode statique nommée Foo, et la sous-classe possède une méthode statique appelé Foo.

Un autre scénario est que le parent a une méthode statique nommée Cat et que la sous-classe a une méthode d'instance nommée Cat. (statique et instance avec la même signature ne peuvent pas se mélanger).

public class Animal {

  public static String getCat() { return "Cat"; }

  public boolean isAnimal() { return true; }
}

public class Dog extends Animal {

  // Method hiding
  public static String getCat() { }

  // Not method hiding
  @Override
  public boolean isAnimal() { return false; }
}
 1
Author: Jeremy Unruh, 2013-05-01 06:28:20