2013-03-20 7 views
12

Ich habe ein Objekt einer anonymen Klasse instanziiert, zu der ich eine neue Methode hinzugefügt habe.Aufruf der neu definierten Methode aus der anonymen Klasse

Date date = new Date() { 

     public void someMethod() { } 

    } 

Ich frage mich, ob es möglich ist, außerhalb dieser Methode nennen von irgendwie ähnlich zu:

date.someMethod(); 
+2

Warum versuchst du es nicht und sehen, ob es kompiliert und läuft? – Claudiu

+2

Warum eine anonyme Klasse verwenden - was ist Ihre Motivation dafür? Tatsächlich ist dies eine Situation, in der es am besten ist, ** anonyme Klassen nicht zu verwenden. –

+1

Sie könnten es wahrscheinlich mit Reflektion tun, aber Sie wollen wahrscheinlich nicht ... – Lucas

Antwort

22

Gute Frage. Antwort ist Nein. Sie können nicht direkt anrufen date.someMethod();
Lassen Sie uns zuerst verstehen, was das ist.

Date date = new Date() { ... }; 

Above anonym ist (habe keinen Namen) Unterklasse, die Date-Klasse erweitert.

Wenn Sie den Code sehen wie,

Runnable r = new Runnable() { 

     public void run() { 

     } 

    }; 

Es heißt, Sie anonym definiert haben (habe keinen Namen) Klasse, die (nicht erstreckt) Runnable-Schnittstelle implementiert.

Also, wenn Sie anrufen date.someMethod() es wird nicht in der Lage sein zu nennen, weil someMethod ist nicht in superclass. In obigem Fall Superklasse definiert ist Date Klasse. Es folgt einfachen Vorrangregeln.

Aber immer noch, wenn Sie someMethod aufrufen möchten, dann folgt der Schritt.

Fisrt Weg>
Mit Bezugsgröße 'date'
date.getClass().getMethod("someMethod").invoke(date);

Zweiter Weg>
Mit neu erstellten anonymer Unterklasse des Objekts Date-Klasse.

new Date() 
{ 
    public void someMethod() { 
      System.out.println("Hello"); 
    } 
}.someMethod(); //this should be without reference 'date' 
8

Ohne Reflexion verwenden Sie können nicht: das Verfahren ist nicht Teil des Date-API und date ist nur ein Datum soweit der Compiler betroffen ist.

Die einzige Möglichkeit, someMethod verwenden können, ist, indem es auf die neu erstellte Instanz aufrufen direkt:

new Date() { public void someMethod() { } }.someMethod(); 
+0

Huh, mir war nicht bewusst, dass Sie beim Erstellen eine Nicht-API-Methode aufrufen könnten. Ich frage mich, was der Zweck dafür ist? – iamnotmaynard

+0

@iamnotmaynard Möglicherweise gibt es keinen Zweck. Es ist nur so, dass der Typ eines anonymen inneren Klassenausdrucks die innere Klasse ist, nicht der benannte Elternteil. Es ist also eher ein Fall, in dem der Compiler Sie ** nicht daran hindert, öffentliche Methoden einer AIC aufzurufen, auch wenn sie nirgendwo sonst zugänglich sind. – millimoose

+0

Ich habe es nie benutzt, um ehrlich zu sein, aber es macht aus der Sicht des Compilers Sinn. – assylias

8

Grundsätzlich nicht.

jedoch Dieses uglyness kann es tun ...

Date date = new Date() { 
    public Date someMethod() { 
    //do some stuff here 
    return this; 
    } 
}.someMethod(); 

Aber abgesehen von dieser, werden Sie nur in der Lage sein, diese Methode aufzurufen, nur mithilfe von Reflektion (die in der übergeordneten Klasse nicht existiert) wie folgt :

date.getClass().getMethod("someMethod").invoke(date); 

(try-catch aus Gründen der Übersichtlichkeit weggelassen ...)

Aber im ernst, dies nicht tun! Ich würde mich von der Person, die diesen Code geschrieben hat, verhasst fühlen, wenn ich in einer Codebase darüber stolpere, an der ich arbeiten muss.

1

Ich weiß nicht, warum Sie dies tun würden, aber wie geschrieben ist es nicht möglich, weil Date nicht someMethod deklariert.

auch immer Sie eine lokale Klasse innerhalb der Methode deklarieren kann, z:

void foo () 
{ 
    class MyDate extends Date 
    { 
    public void someMethod(); 
    } 

    MyDate date = new MyDate(); 

    date.someMethod(); 
} 

Noch einmal, ich würde vorschlagen, zunächst eine normal-Klasse, weil die lokalen Klassen, die ihrer Natur nach nicht getestet werden kann.

2

Nein, dafür gibt es Methoden - lokale Klassen.

class MyDate extends Date() { 
    public void someMethod() {...} 
} 
MyDate date = new MyDate(); 
date.someMethod(); 
+0

Diese Antwort ist falsch. – Pacerier

Verwandte Themen