Les méthodes statiques sont-elles héritées de Java?

143

Je lisais un guide du programmeur sur la certification Java ™ SCJP par Khalid Mughal.

Dans le chapitre Héritage, il explique que

L'héritage des membres est étroitement lié à leur accessibilité déclarée. Si un membre de superclasse est accessible par son nom simple dans la sous-classe (sans utiliser de syntaxe supplémentaire comme super), ce membre est considéré comme hérité

Il mentionne également que les méthodes statiques ne sont pas héritées. Mais le code ci-dessous est parfait:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

Comment puis-je utiliser directement display()en classe B? Encore plus, B.display()fonctionne également.

L'explication du livre s'applique-t-elle uniquement aux méthodes d'instance?

Algorithmiste
la source
stackoverflow.com/questions/4716040/… a des informations intéressantes.
Mat
Ce n'est pas ce qu'il dit dans mon exemplaire, 1ère édition. Veuillez fournir un devis réel.
Marquis of Lorne

Réponses:

180

Toutes les méthodes accessibles sont héritées par les sous-classes.

À partir des didacticiels Sun Java :

Une sous-classe hérite de tous les membres publics et protégés de son parent, quel que soit le package dans lequel se trouve la sous-classe. Si la sous-classe est dans le même package que son parent, elle hérite également des membres package-private du parent. Vous pouvez utiliser les membres hérités tels quels, les remplacer, les masquer ou les compléter avec de nouveaux membres

La seule différence avec les méthodes statiques héritées (de classe) et les méthodes non statiques héritées (instance) est que lorsque vous écrivez une nouvelle méthode statique avec la même signature, l'ancienne méthode statique est simplement masquée et non remplacée.

À partir de la page sur la différence entre le remplacement et le masquage.

La distinction entre cacher et passer outre a des implications importantes. La version de la méthode remplacée qui est appelée est celle de la sous-classe. La version de la méthode masquée qui est invoquée dépend du fait qu'elle soit invoquée depuis la superclasse ou la sous-classe

yincrash
la source
donc hérité se rapporte à savoir si nous pouvons remplacer ce membre dans la sous-classe?
Algorithmiste
Eh bien, cela fait partie de l'héritage, mais pas du tout. Je dirais que les autres éléments majeurs de l'héritage sont la réutilisation du code et le polymorphisme.
yincrash
La redéfinition a-t-elle également des règles comme la dérogation?
Surender Thakran
2
@Algorithmist non pas exactement. Toutes les choses que votre sous-classe voit plus haut dans la hiérarchie sont des choses dont votre classe a hérité. Mais les méthodes statiques héritées ne peuvent pas être écrasées, seulement masquées («redéclarées» avec la même signature). Par conséquent, vous pouvez également déclarer vos méthodes statiques comme finales, cela n'a pas d'importance. La méthode statique qui sera appelée est connue au moment de la compilation. Avec les méthodes d'instance non finale, la résolution doit être différée à l'exécution car elles peuvent être remplacées.
Martin Andersson
1
Votre dernier paragraphe est complètement miné !!! "La version de la méthode surchargée qui est invoquée est celle de la sous-classe" ce n'est pas vrai: disons: la version de la méthode surchargée qui est invoquée est uniquement déterminée au moment de l'exécution par la JVM en fonction de quel objet call :)
mounaim
14

Si c'est ce que dit vraiment le livre, c'est faux. [1]

La spécification du langage Java # 8.4.8 stipule:

8.4.8 Héritage, remplacement et masquage

Une classe C hérite de sa superclasse directe toutes les méthodes concrètes m (statiques et d'instance) de la superclasse pour lesquelles toutes les conditions suivantes sont vraies:

  • m est membre de la superclasse directe de C.

  • m est public, protégé ou déclaré avec un accès au package dans le même package que C.

  • Aucune méthode déclarée en C n'a une signature qui est une sous-signature (§8.4.2) de la signature de m.

[1] Cela ne dit pas dans mon exemplaire, 1ère édition, 2000.

Marquis de Lorne
la source
13

Vous pouvez constater la différence dans le code suivant, qui est légèrement modifié par rapport à votre code.

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

Cela est dû au fait que les méthodes statiques sont des méthodes de classe.

A.display () et B.display () appelleront la méthode de leurs classes respectives.

Gaurav
la source
1
L'appel d'une méthode statique sur une instance comme vous essayez de ne pas fonctionner en java.
Lucas C. Feijo
C'est ce que ce programme explique, instancier l'objet de B et s'attendre à ce que l'héritage fonctionne ne sera pas possible avec des membres statiques. Essayez de prendre le même code dans votre éclipse / n'importe quel ide ou compilez en utilisant javac et exécutez-le
Gaurav
2
@ LucasC.Feijo en fait, ça marche. Au moins dans mon IDE (éclipse). Je reçois juste un avertissement. Ce n'est peut-être pas du bon style ... mais c'est une autre histoire.
dingalapadum
2
@ LucasC.Feijo appeler une méthode statique sur une instance n'est pas recommandé. Mais cela fonctionne de la même manière que l'appel d'une méthode statique sur un nom de classe.
Ziyang Zhang
5

B.display () fonctionne parce que la déclaration statique fait que la méthode / le membre appartient à la classe, et non à une instance de classe particulière (aka Object). Vous pouvez en savoir plus ici .

Une autre chose à noter est que vous ne pouvez pas remplacer une méthode statique, vous pouvez demander à votre sous-classe de déclarer une méthode statique avec la même signature, mais son comportement peut être différent de ce à quoi vous vous attendez. C'est probablement la raison pour laquelle il n'est pas considéré comme hérité. Vous pouvez consulter le scénario problématique et l'explication ici .

Kai
la source
3

Les méthodes statiques en Java sont héritées, mais ne peuvent pas être remplacées. Si vous déclarez la même méthode dans une sous-classe, vous masquez la méthode de la superclasse au lieu de la remplacer. Les méthodes statiques ne sont pas polymorphes. Au moment de la compilation, la méthode statique sera liée statiquement.

Exemple:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

Vous obtiendrez ce qui suit:

Writing
Writing
Writing
Writing book

la source
2

Les méthodes statiques sont héritées en Java mais elles ne participent pas au polymorphisme. Si nous essayons de remplacer les méthodes statiques, elles masqueront simplement les méthodes statiques de la superclasse au lieu de les remplacer.

Praveen Kumar
la source
Je ne vois pas de raison de voter contre cette réponse. C'est net et clair, du moins la première partie. La deuxième partie ne doit pas être prise trop techniquement, sinon ça va. Pour clarifier, dans les méthodes de substitution, le type de retour peut changer (en sous-type) alors que ce n'est pas le cas avec les méthodes statiques. Techniquement, «tenter de remplacer» ne s'applique pas aux méthodes statiques, donc tout ce que nous pouvons dire, c'est que nous ne pouvons pas.
sharhp
2

Ce concept n'est pas aussi simple qu'il y paraît. Nous pouvons accéder aux membres statiques sans héritage, qui est la relation HasA. Nous pouvons accéder aux membres statiques en étendant également la classe parente. Cela n'implique pas qu'il s'agit d'une relation ISA (héritage). En fait, les membres statiques appartiennent à la classe et static n'est pas un modificateur d'accès. Tant que les modificateurs d'accès permettent d'accéder aux membres statiques, nous pouvons les utiliser dans d'autres classes. Comme s'il est public, il sera accessible à l'intérieur du même package et également à l'extérieur du package. Pour le privé, nous ne pouvons l'utiliser nulle part. Par défaut, nous ne pouvons l'utiliser que dans le package. Mais pour protégé, nous devons étendre la super classe. Donc, obtenir la méthode statique dans une autre classe ne dépend pas du fait d'être statique. Cela dépend des modificateurs d'accès. Donc, à mon avis, Les membres statiques peuvent accéder si les modificateurs d'accès le permettent. Sinon, nous pouvons les utiliser comme nous les utilisons par Hasa-relation. Et a une relation n'est pas un héritage. Encore une fois, nous ne pouvons pas remplacer la méthode statique. Si nous pouvons utiliser une autre méthode mais ne pouvons pas la remplacer, alors c'est HasA-relation. Si nous ne pouvons pas les remplacer, ce ne sera pas l'héritage, donc l'écrivain était correct à 100%.

Noman_ibrahim
la source
L'extension de la classe parente est une relation «est-un». Si l'accès est privé, vous pouvez l'utiliser depuis la classe. 'protected' inclut les classes dérivées et les classes dans le package actuel. Trop d'erreurs ici.
Marquis of Lorne
0

La méthode statique est héritée de la sous-classe mais ce n'est pas du polymorphisme. Lorsque vous écrivez l'implémentation de la méthode statique, la méthode de classe du parent est masquée et non remplacée. Réfléchissez, s'il n'est pas hérité, comment pouvez-vous y accéder sans classname.staticMethodname();?

utilisateur4016405
la source
0

Tous les membres publics et protégés peuvent être hérités de n'importe quelle classe tandis que les membres par défaut ou du package peuvent également être hérités de la classe dans le même package que celui de la superclasse. Cela ne dépend pas s'il s'agit d'un membre statique ou non statique.

Mais il est également vrai que la fonction membre statique ne participe pas à la liaison dynamique. Si la signature de cette méthode statique est la même dans les classes parent et enfant, alors le concept de Shadowing s'applique, pas le polymorphisme.

Shubham
la source
0

Vous pouvez remplacer les méthodes statiques, mais si vous essayez d'utiliser le polymorphisme, elles fonctionnent selon la portée de la classe (contrairement à ce que nous attendons normalement).

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

DANS le premier cas, o / p est la "méthode statique de B" # remplacement réussi Dans le 2ème cas, o / p est "dans la méthode statique de A" # Méthode statique - ne considérera pas le polymorphisme

Manav Garekar
la source
-1

Nous pouvons déclarer des méthodes statiques avec la même signature dans la sous-classe, mais cela n'est pas considéré comme écrasant car il n'y aura pas de polymorphisme à l'exécution, car tous les membres statiques d'une classe sont chargés au moment du chargement de la classe, il décide donc à la compilation time (remplacement au moment de l'exécution) La réponse est donc «Non».

NGK
la source
2
Je ne sais pas pourquoi les gens votent toujours contre et ne donnent pas la raison de voter contre.
surajs1n
Cette réponse concerne la priorité. La question concerne l'héritage.
Marquis of Lorne
-1

Beaucoup ont exprimé leur réponse avec des mots. Ceci est une explication étendue dans les codes:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

Résultats:

A
B

Test
Test

A
B

Test
Test

A

A

Par conséquent, voici la conclusion:

  1. Lorsque nous appelons le static de manière statique via., Il recherchera le static défini dans cette classe, ou la classe la plus proche de celle dans la chaîne d'héritage. Cela prouve que les méthodes statiques sont héritées.
  2. Lorsque la méthode statique est appelée à partir d'une instance, elle appelle la méthode statique définie dans le type à la compilation.
  3. La méthode statique peut être appelée à partir d'une nullinstance. Je suppose que le compilateur utilisera le type de variable pour trouver la classe lors de la compilation et la traduira par l'appel de méthode statique approprié.
I have
la source
1
Le simple code n'est pas une explication, c'est une démonstration. Une réponse à cette question devrait citer des références normatives, et pas seulement montrer le comportement d'une implémentation non déclarée.
Marquis of Lorne
-2

Les membres statiques sont des membres universels. Ils sont accessibles de n'importe où.

Pavan
la source
4
peut être accédé de n'importe où pris littéralement, c'est faux: static! = scope. vous voudrez peut-être clarifier :-)
kleopatra
En fait, cette réponse est bien prise à la lettre. Je ne peux pas penser à un seul endroit dans le code où le code peut aller et que l'on ne peut pas accéder à un membre statique de la classe. Vous pouvez y accéder dans des initialiseurs statiques, des constructeurs statiques, des constructeurs d'instances, des méthodes, des propriétés, dans différentes classes, dans n'importe quelle portée. Tant que la classe et la méthode statique sont publiques, elles sont accessibles de n'importe où, en supposant qu'il n'y ait pas de dépendances circulaires sur les initialiseurs statiques. Par essence, les membres statiques ne sont pas hérités, ce sont juste des méthodes de niveau classe (c'est-à-dire universelles) qui sont accessibles de n'importe où.
Triynko
@Triynko La réponse est erronée dans le cas de méthodes privées ou protégées par package accessibles depuis l'extérieur du package.
Marquis de Lorne
@kleopatra - hors sujet. balançoire java? les gens l'utilisent-ils réellement ces jours-ci?
MasterJoe
@Pavan essaie d'appeler des statiques privés depuis l'extérieur de la classe. Ça ne marchera pas.
Rakesh Yadav
-2

Les membres statiques ne seront pas hérités de la sous-classe car l'héritage concerne uniquement les membres non statiques. Et les membres statiques seront chargés dans le pool statique par le chargeur de classe. L'héritage concerne uniquement les membres chargés à l'intérieur de l'objet

Ashwini E
la source
Complètement incorrect. Voir JLS # 8.4.8 .
Marquis of Lorne