2013-09-06 10 views
21

den folgenden Code vor:eine willkürlich definierte Methode eines anonymen Schnittstelle verwenden

public static void main(String[] args) { 
    File file = new File("C:\\someFile.txt") { 
     public void doStuff() { 
      // Do some stuff 
     } 
    }; 

    file.doStuff(); // "Cannot resolve method" 
} 

Wenn wir versuchen, unsere neu definierte Methode doStuff() zu nennen, ist es nicht möglich. Der Grund dafür ist, dass file als ein Objekt vom Typ File deklariert ist und nicht als eine Instanz unserer neuen, anonymen Kindklasse.

Also, meine Frage ist, gibt es eine "nette" Möglichkeit, dieses Verhalten zu erreichen? Anders als das Offensichtliche (das ist nur, um die Klasse richtig zu deklarieren).

+3

http://stackoverflow.com/questions/8697971/anonymous-class-method-access - Sie sind nicht „überschrieben“ alles hier, was die üblichere Verwendung von anonymen Klassen, so dass Ihre Methode würde nur verfügbar sein innerhalb Ihrer anonymen Klasse oder wenn Sie etwas mit Reflektion –

+0

'extend' getan haben, ist nett genug für mich. –

+0

Sie können eine anonyme Klasse verwenden, aber Sie können keine anonyme Schnittstelle haben. –

Antwort

16

Das ist nicht möglich, weil Sie versuchen, die Methodenunterklasse auf Superklassenreferenz aufzurufen. Und diese Methode ist nicht in der Superklasse selbst definiert. Die anonyme Klasse ist nur eine Unterklasse von File dort.

ist jedoch eine Abhilfe durch Reflexion gehen:

file.getClass().getMethod("doStuff").invoke(file); 

Die getClass() Methode wird die Laufzeittyp von file zurückzukehren, und dann können Sie die Methode für diese Klasse mit Class#getMethod() Methode erhalten.

Nun, ich bin selbst kein großer Fan der Reflexion. Ein besserer Weg wäre natürlich, eine Klasse zu erstellen, indem man die Superklasse erweitert, wenn man solche Sachen macht. Es wäre wirklich ein Schmerz im Kopf, der sich durch Reflexion herausarbeitet, was mit einer einfachen Modifikation leicht gemacht werden kann.

+0

'file.getClass(). GetMethod (" doStuff "). Invoke();' ist hier nicht funktionsfähig. –

+0

@ Ruchira. Was meinst du damit? –

+0

RE: Ihre Bearbeitung über die Gefahren der Reflexion: Das ist in Ordnung, ich bin nicht im Begriff, Reflexion überall zu verwenden. Dies war eine rein theoretische Frage, und das ist die beste Antwort. – Xenoprimate

7

Der nette Weg ist nicht anonyme innere Klasse in Ihrem Fall zu verwenden, sondern definieren Sie Ihre eigene Klasse, die File erweitert und fügen Sie alle Methoden, die Sie dort benötigen.

class StuffedFile extends File { 
    // implement all needed constructors 
    public void doStuff() { /*.....*/} 
} 

Jetzt können Sie es wie folgt verwendet werden:

MyFile f = new MyFile("..."); 
f.doStuff(); 

diesen Versuch jedoch ganze File zu verlängern nicht als gutes Design klingen. Erstellen Sie eine andere Klasse, die eine Datei akzeptieren und darauf zugreifen kann. Sie erreichen eine bessere Kapselung und Code-Wiederverwendbarkeit.

EDIT Offensichtlich können Sie Reflexion verwenden, um jede Methode aufzurufen, die Sie wollen, aber ich kann diese "nette Lösung" nicht nennen. Ich kann dies "mögliche Abhilfe" nennen.

+0

Der Code war nur ein Beispiel, ich mache nichts mit File. Außerdem suchte ich nach einer "sauberen" Syntax, ohne eine neue Klasse erstellen zu müssen. Ich weiß, dass ich File einfach erweitern kann. – Xenoprimate

+5

+1 für nicht empfohlen Reflexion –

+1

Wäre es nicht klarer, MyFile in die definierte Klasse StuffedFile zu ändern? – Timo

2

Der nächste ich in der Lage gewesen, um Ihr Niveau der Prägnanz zu erhalten ist:

public static void main(String[] args) { 
    abstract class FileThatDoesStuff extends File { 
    // Need a constructor that takes a String because File has one. 
    public FileThatDoesStuff(String filePath) { 
     super(filePath); 
    } 
    // It also does stuff. 
    public abstract void doStuff(); 
    } 
    FileThatDoesStuff file = new FileThatDoesStuff("C:\\someFile.txt") { 
    @Override 
    public void doStuff() { 
     // Do some stuff 
    } 

    }; 
    file.doStuff(); // "Can resolve method" 
} 

Ich muss zugeben, ich wünschte, ich könnte:

abstract class DoesStuff<T> extends T { 
    public abstract void doStuff(); 
} 
+0

Curmudgeon: C# bietet dies mit Erweiterungsmethoden (das letzte Verhalten, das Sie dort angeben). Einer der Gründe, warum ich C# liebe :) – Xenoprimate

0

Es ist möglich, diese Methode für den Zugriff auf . Aber ich weiß nicht, warum du das jemals tun würdest.

public static void main(String[] args) { 
    new File("C:\\someFile.txt") { 
     public void doStuff() { 
      // Do some stuff 
     } 
    }.doStuff(); 
} 
Verwandte Themen