web-dev-qa-db-fra.com

Appel de la fonction de substitution de classe de base à partir de la méthode de classe de base

public class A {
    public void f1(String str) {
        System.out.println("A.f1(String)");
        this.f1(1, str);
    }

    public void f1(int i, String str) {
        System.out.println("A.f1(int, String)");
    }
}



public class B extends A {
    @Override
    public void f1(String str) {
        System.out.println("B.f1(String)");
        super.f1(str);
    }

    @Override
    public void f1(int i, String str) {
        System.out.println("B.f1(int, String)");
        super.f1(i, str);
    }
}


public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.f1("Hello");
    }
}

Je cherche à ce que ce code produise:

B.f1(String)
A.f1(String)
A.f1(int, String)

Pourtant, je reçois:

B.f1(String)
A.f1(String)
B.f1(int, String)
A.f1(int, String)

Je comprends que dans le contexte de B "ceci" dans A.f1 (String) est l'instance de B. Ai-je la possibilité de faire la nouvelle chaîne B1 (). F1 (String) -> (A's) f1 (String) -> (A's) f1 (int, String)?

C'est une question théorique, pratiquement la solution serait évidemment en A d'implémenter une fonction privée que f1 (String) et f1 (int, String) appellent.

Merci,
Maxime.

38
Maxim Veksler

Malheureusement, non

Comme je suis sûr que vous le savez, mais je préciserai explicitement pour être complet - il n'y a que les 2 mots clés pour contrôler l'invocation de la méthode:

  • this - this.method() - recherche une méthode à partir de la classe de l'instance appelante (la table virtuelle "top" de l'instance - implicite par défaut)
  • super - super.method() - recherche la méthode à partir de la classe parente de la classe dans laquelle la méthode d'appel est définie (la classe d'appel table virtuelle des parents - pas strictement vrai , mais plus simple à penser de cette façon - merci @maaartinus)

Je peux imaginer un autre mot-clé (par exemple actuel?) Faire ce que vous décrivez:

  • current - current.method() - recherche la méthode à partir de la classe dans laquelle la méthode d'appel est définie

mais Java n'a pas encore un tel mot-clé?).

34
Bert F

J'ai peur, c'est impossible, mais il existe une solution simple:

public class A {
    public void f1(String str) {
        System.out.println("A.f1(String)");
        privateF1(1, str);
    }

    private void privateF1(int i, String str) {
        System.out.println("A.f1(int, String)");
    }

    public void f1(int i, String str) {
        privateF1(i, str);
    }
}
19
maaartinus

Les méthodes écrasées dans Java sont liées dynamiquement. C'est-à-dire que le type de l'instance réelle de l'objet dicte ce qui sera appelé. final méthodes (qui ne peuvent pas être écrasées) et Les méthodes private (qui ne peuvent pas être héritées) sont liées statiquement.

En C++, pour le contraste, il faudrait explicitement faire les fonctions virtual pour obtenir le même comportement.

6
Brian Agnew