2011-08-17 2 views
7

Ho una classe Java astratta che deve essere implementata con un metodo onMessage. So che una chiusura può facilmente implementare un'interfaccia Java usando la parola chiave as, ma come può estendere una classe Java astratta?Una chiusura Groovy può estendere una classe astratta

Se non è possibile estenderlo, allora quale è il miglior lavoro possibile in questi casi in Groovy?

Ecco il mio utilizzo in Java, sto cercando qualcosa di simile che possa essere fatto in Groovy.

MessageCallback callback = new MessageCallback() { 
      @Override 
      public void onMessage(Message message) { 
       dosomething(); 
      } 
     }; 

Dove messaggio di richiamata è la mia classe astratta che vorrei utilizzare in modo simile in Groovy.

risposta

7

Credo che si dovrebbe essere in grado di fare:

def callback = [ onMessage:{ message -> doSomething() } ] as MessageCallback 

Vuol non funziona?

Modifica

Per effettuare una chiamata dal metodo Map torna alla classe astratta, l'unico modo che riesce a trovare per farlo è:

// Dummy class for testing 
abstract class MessageTest { 
    abstract void onMessage(msg) ; 
    void done() { println "DONE!" } 
} 

// Create a Proxied instance of our class, with an empty onMessage method 
def p = [ onMessage:{ msg -> } ] as MessageTest 

// Then overwrite the method once we have access to the Proxy object p 
p.metaClass.onMessage = { msg -> println msg ; p.done() } 

// Test 
p.onMessage('woo') 
+2

Che dovrebbe funzionare. Infatti, se MessageCallback ha solo un metodo, puoi farlo: def callback = {message -> doSomething()} come MessageCallback –

+0

@tim_yates Ha funzionato parzialmente, la classe messagecallback aveva un metodo "done" che quando ho invocato all'interno la chiusura, ho ottenuto l'eccezione metodo mancante. In java uso solo done(), dovrei usare qualche altra sintassi in Groovy? – Abe

+1

Ahhh, se hai bisogno di richiamare la classe Proxied le cose si complicano ... darò un'occhiata e vedrò se riesco a trovare qualcosa di meglio che scrivere una classe concreta con metodi vuoti, e poi sovrascriverli nella ' metaClass' (che è l'unica altra soluzione che posso attualmente pensare) –

2

Yo può fare questo:

implementa un metodo in ogni classe:

public MessageTest messageTest(Closure callback) { 
    return new MessageTest() { 
     @Override 
     public void onMessage(Message message) { 
      callback.call(message) 
     } 
    } 
} 

In classe principale nel metodo main:

def outerMessage 

MessageTest messageTest = messageTest() {message -> 
    outerMessage = message 
    println "innerMessage: $message" 
} 

messageTest.onMessage("This is the message...") 
println "outerMessage: $outerMessage" 

L'output dovrebbe mostrare questo:

innerMessage: This is the message... 
outerMessage: This is the message... 
1

basandosi su @tim_yates, qui è una versione del metodo che crea oggetto di una classe astratta da una chiusura. Avevo bisogno di qualcosa del genere per poter istanziare tale oggetto in una sola riga.

// Dummy class for testing 
abstract class MessageTest { 
    abstract void onMessage(msg) ; 
    void done() { println "DONE!" } 
} 

MessageTest createMessageTest(Closure closure) { 
    // Create a Proxied instance of our class, with an empty onMessage method 
    def p = [ onMessage:{ msg -> } ] as MessageTest 

    // Then overwrite the method once we have access to the Proxy object p 
    p.metaClass.onMessage = closure 
    return p 
} 

// Create 
MessageTest mt = createMessageTest { msg -> 
    println msg ; 
    done() 
} 

// Test 
mt.onMessage('woo')