2013-01-16 4 views
3

Je ne suis pas en mesure de trouver un bon résumé pour décrire mon problème (suggestions bienvenues)Appel de la méthode superclasse dans superclasse

Je suit deux classes:

Test1

import java.lang.reflect.Method; 

abstract class Test1 { 

    boolean condition = true; 

    public void f() { 
     System.out.println("Test1 : f"); 
    } 

    public void g() { 
     System.out.println("Test1 : g"); 
     f(); 
     if (condition) { 
      f(); // call Test1.f() here. HOW? 

      // Following didn't work 
      try { 
       Method m = Test1.class.getDeclaredMethod("f"); 
       m.invoke(this); 
      } catch (Exception e) { 
       System.err.println(e); 
      } 
     } 
    } 
} 

Test2

class Test2 extends Test1 { 

    public void f() { 
     System.out.println("Test2 : f "); 
    } 

    public static void main(String[] args) { 
     Test2 t2 = new Test2(); 
     t2.g(); 
    } 

} 

La sortie est:

Test1 : g 
Test2 : f 
Test2 : f 
Test2 : f 

Le problème est que, en raison d'une condition spéciale donnée par le champ condition dans Test1 Je veux appeler Test1 « s f() dans g() même si je fais appel à l'aide d'un objet de Test2.

J'ai essayé la réflexion mais cela ne fonctionne pas non plus. Aucune suggestion? Je n'ai pas mentionné spécifiquement, mais si vous voyez attentivement Test1 est abstrait. Donc je ne peux pas créer son objet.

Répondre

1

Ajouter une méthode f2 dans Test1:

private void f2() { 
    System.out.println("Test1 : f"); 
} 
public void f() { 
    this.f2() 
} 

De cette façon, vous pouvez appeler f2() lorsque la condition est vraie.

3

Vous devriez sérieusement considérer la logique que vous essayez de construire. La raison pour laquelle vous avez essayé de remplacer la méthode f dans la classe enfant a certainement une raison derrière elle.

Vous pouvez également avoir une valeur booléenne comme retour de la méthode f et dans la méthode enfant utiliser boolean r = super.f(); if(r){//execute child logic.} Cela devrait résoudre votre problème.

+0

La logique est complexe, c'est vrai. Mais je ne vois pas votre point, 'super.f()' renvoie 'void', ce n'est pas assignable à booléen. – gaborsch

+0

Je recommandais de changer void en booléen. Cela aidera à prendre la décision sur l'exécution de la logique de la méthode enfant. – CuriousMind

+0

La logique, que ce soit pour appeler le parent ou non, vient de la logique interne de 'g()'. Il ne peut pas être implémenté pour tous les appels à 'f()' (par exemple à partir d'un appel de 'h()'). – gaborsch

0

Si le nom de la méthode est identique, vous ne pouvez pas le faire.
D'une autre manière, il est possible d'appeler directement les méthodes super classe dans la sous-classe en utilisant super.f().

0

UPD: spécialement pour cette personne, qui n'est pas très attentive, je donne l'explication .

Dans mon code ci-dessous, je crée une nouvelle anonyme en utilisant les parenthèses { }. Cela me permet de faire une nouvelle instance de sous-classé Test1.


Au lieu d'utiliser reflection, vous pouvez le faire une telle chose drôle:

public void g() { 
    System.out.println("Test1 : g"); 
    f(); 
    if (condition) { 
     new Test1(){}.f(); 
    } 
} 

Le seul inconvénient est que f() méthode appelée de telle manière est l'invocation de la méthode d'un autre objet absolument.

+0

Test1 est abstrait, donc je ne peux pas créer son objet. – Xolve

+2

@Xolve, 'new Test1() {}' c'est un objet créé en utilisant une classe anonyme. Donc je peux. – Andremoniy

+0

@Xolve, peut-être que vous n'avez pas remarqué, mais après 'new Test1()' il y a des parenthèses '{}'. – Andremoniy

0

L'héritage permet seulement d'hériter le comportement super.f(), le remplacez @Override ou les deux

@Override 
public void f(){ 
    super.f(); 
    //do something 
} 

Tu ne peux pas remplacer une méthode et essayez d'appeler l'état de la méthode des parents avant qu'il ne soit remplacé. L'héritage ne fonctionne pas comme ça.

2

ce que j'ai compris.

Votre question:
Si g() appelle méthode f() dans Test1 classe Alors pourquoi sa runing f() de classe enfant (Test2).

Réponse: De JLS-8.4.8.1

La sous-classe Test2 déclare une seule méthode f(), qui remplace la méthode f() de Test1. Il hérite des méthodes g() de la classe Test1.

Le point critique sur le remplacement de cet exemple est que la méthode g(), qui est déclarée dans la classe Test1, appelle la méthode f() défini par l'objet en cours this, qui ne sont pas nécessairement la méthode f() déclaré dans la classe Test1.

Ainsi, lorsque g() est invoquée en utilisant le principal objet t2 Test2, l'invocation de f() dans le corps de la méthode g() est une invocation du f() du t2 objet. Cela permet à une sous-classe de Test1 de modifier le comportement de la méthode f() sans la redéfinir.

Commotion:

Donc, si une classe est PRÉPONDÉRANTS une méthode de son contrat, puis parent dit, Test1 qui est conçu pour être étendu, doit indiquer clairement quel est le contrat entre la classe et ses sous-classes, et devrait indiquer clairement que les sous-classes peuvent outrepasser la méthode f() de cette manière.

Questions connexes