Javadoc dit:
la version de la méthode masquée appelée est celle de la superclasse et la version de la méthode substituée appelée est celle de la sous-classe.
ça ne me dit rien. Tout exemple clair montrant la signification de ceci sera très apprécié.
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, on dit que Cat.foo()
cache Animal.foo()
. Masquer ne fonctionne pas comme une substitution, car les méthodes statiques ne sont pas polymorphes. Donc ce qui suit va arriver:
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
L'appel de méthodes statiques sur des instances plutôt que sur 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");
}
}
Ensuite, il se passera ce qui suit:
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
Tout d’abord, qu’entend-on par méthode Cacher?
Méthode masquant les moyens signifie que la sous-classe a défini une méthode class 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 sera ET NON déterminée par l'objet utilisé pour l'invoquer . En fait, elle sera déterminée par la variable type de référence utilisée pour appeler la méthode.
Qu'entend-on par méthode prioritaire?
Méthode redéfinissant signifie que la sous-classe a défini une méthode d'instance avec la même signature et le même type de retour (y compris le type de covariant) que la méthode d'instance de la superclasse. Dans ce cas, la méthode de 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 utilisé pour l'invoquer . Il ne sera pas déterminé par le type de variable de référence utilisé pour appeler 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 à laquelle elles sont appelées et non de manière dynamique comme dans le cas des méthodes d'instance résolues de manière polymorphe en fonction du type d'exécution de l'objet.
Comment faut-il accéder aux méthodes statiques?
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 par une instance.
Voici la brève démonstration de la méthode qui masque et masque:
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.
}
}
La 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 (i.e Super ou Child) référençant l’objet de Child
. Si elle est référencée par la variable Super
, alors foo
de Super
est appelé. Et si elle est référencée par la variable Child
, alors foo
de Child
est appelé.
Tandis que,
Puisque bar
est la méthode de l'instance, la version de bar
invoquée est uniquement déterminée par l'objet (c'est-à-dire Child
) utilisé pour l'appeler. Peu importe la variable de référence (Super
ou Child
), la méthode à appeler est toujours de Child
.
Pour é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 est appelée.
Pour cacher une méthode, cela 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) va maintenant appeler une fonction complètement différente , nécessitant une qualification pour accéder à la méthode statique du même nom à partir de la classe parente.
Plus de description Héritage Java: Méthodes écrasées ou masquées
Si une sous-classe définit une méthode de classe avec la même signature qu'une méthode de classe dans la superclasse, la méthode de la sous-classe masque celle de la superclasse.
Les méthodes cachées sont dans un contexte statique, je crois. Les méthodes statiques ne sont pas substituées en soi, car la résolution des appels de méthodes effectuée par le compilateur au moment de la compilation elle-même. Ainsi, 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 parent, la méthode de la sous-classe masque 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");
}
}
Par exemple, vous pouvez substituer des méthodes d'instance dans une super classe mais pas statique.
Hiding is Parent class a une méthode statique appelée Foo et la sous-classe a également une méthode statique appelée Foo.
Un autre scénario est que le parent a une méthode statique appelé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 être mélangés).
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; }
}
class P
{
public static void m1()
{
System.out.println("Parent");
}
}
class C extends P
{
public static void m1()
{
System.out.println("Child");
}
}
class Test{
public static void main(String args[])
{
Parent p=new Parent();//Parent
Child c=new Child(); //Child
Parent p=new Child(); //Parent
}
}
If the both parent and child class method are static the compiler is responsible for method resolution based on reference type
class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent
Child c=new Child(); //Child
Parent p=new Child(); //Child
}
}
If both method are not static jvm is responsible for method resolution based on run time object