2015-01-26 3 views
13

Stellen wirAufruf Super Methode aus einer anonymen inneren Klasse innerhalb des überschriebenen Methode

class A { 

    public void m() { 
    System.out.println("A - > m()"); 
    } 
} 

und ich möchte die Methode m() überschreiben auf Klassenerstellung ohne Herstellung einer zweiten Unterklasse B eine Klasse erweitern A.

public static void main(String[] args) { 
    A a = new A() { 

     @Override 
     public void m() { 
      System.out.println("Override - > m()"); 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        // I want to be able to call the super method. 
        // This is illegal! 
        A.super.m(); 
       } 
      }).start(); 
     } 
    }; 
    a.method(); 
} 

Derzeit meine Lösung ist eine private Methode zu erstellen, die die super.m nennt()

A a = new A() { 

     private void superMethod() { 
      super.m(); 
     } 

     @Override 
     public void m() { 
      System.out.println("Overrided - > m()"); 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        superMethod(); 
       } 
      }).start(); 
     } 
    }; 
    a.m(); 

Ich möchte wissen, warum ich A.super.m() nicht schreiben kann und gibt es eine andere Möglichkeit, diese Aufgabe auszuführen.

+0

Könnte ein [local Klasse] (http://docs.oracle.com/javase/ tutorial/java/javaOO/localclasses.html) Ihren Bedürfnissen entsprechen? – sp00m

+0

Nun, es könnte, aber das war tatsächlich, was ich versuchte zu vermeiden. – kirilv

Antwort

8

Ich möchte wissen, warum ich nicht in der Lage bin A.super.m() zu schreiben ...

Dies liegt daran, A in der Tat ist nicht eine direkt umschließenden Klasse. Die direkt einschließende Klasse der Runnable ist new A() { ... }, die eine anonyme Unterklasse von A ist.

Mit anderen Worten, wenn Sie

gehabt hätte
class A extends Base { 
    new Runnable() { ... } 
} 

dann würde A.super gearbeitet haben, aber jetzt haben Sie

class <Anonymous subclass of A> extends A { 
    new Runnable() { ... } 
} 

was bedeutet, dass so etwas wie A.super nicht möglich ist, da es keine Syntax für <Anonymous subclass of A>.super.m.

... und gibt es eine andere Möglichkeit, diese Aufgabe auszuführen.

Die Art, wie Sie es gelöst haben, ist meiner Meinung nach vernünftig.Eine andere Möglichkeit wäre eine lokale Unterklasse von A zu erstellen (nur eine Kennung einzuführen in ____.super.m zu verwenden) wie folgt:

public static void main(String[] args) { 

    class SubA extends A { 
     @Override 
     public void m() { 
      System.out.println("Override - > m()"); 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        SubA.super.m(); 
       // ^^^^ we now have a name of the directly enclosing class 
       } 
      }).start(); 
     } 
    } 
    A a = new SubA(); 
    a.m(); 
} 
4

Schreiben A.super.m(), angenommen, dass A eine Oberklasse mit einer m-Methode hat. In Ihrem Code geben Sie jedoch keine Oberklasse an, und die einzige Oberklasse, die Sie haben, ist standardmäßig Object.
Aber Object-Klasse hat keine "M" -Methode, so dass Sie sie nicht aufrufen konnten. Ein guter Weg, um so etwas zu tun, ist die Verwendung von Design-Muster, wie Dekorateur.

+0

Nicht ganz sicher, ob ich folge ... neu A() {...} hat Superklasse A, nein? – aioobe

+0

Wenn ich keinen Fehler mache ja :) – vincent

+0

Lesen Sie Ihre Antwort, es sieht aus wie Sie sagen, dass A hat keine Super-Klasse mit der Methode m. Ich kann nicht sehen, wie das zusammenhängt. Die Fehlermeldung, die Sie erhalten, wenn Sie versuchen, diesen Code zu kompilieren, besteht nicht darin, dass dem Objekt die Methode m fehlt, sondern dass A. dies kein gültiger Ausdruck ist. – aioobe

3

Ich glaube nicht, dass es eine einfachere Möglichkeit geben würde, es anders zu machen als die, die Sie bereits haben. Das Problem ist, dass die anonyme Klasse A selbst (nicht die Basisklasse A) nicht innerhalb der Klasse Runnable referenziert werden kann. Die anonyme Klasse wird als etwas wie package.A$1 dargestellt, wenn sie in eine eigene Klassendatei kompiliert wird. Zum Beispiel, wenn man superMethod innerhalb der run des Gewindes nennt, wird die folgende Bytecode ausgeführt:

getfield mypackage/Test$1$1/this$1 Lmypackage/Test$1; 
invokestatic mypackage/Test$1/access$0(Lmypackage/Test$1;)V 

Um seine Basisklasse A, referenzieren kein Hinweis auf diese innere Klasseninstanz ist, so dass Sie den Anruf super.m() Ausdruck.

Verwandte Themen