2010-08-23 17 views
7

Mi piacerebbe ri-implementare un metodo di una classe Java. Ad esempio, per "hi".length() restituire 4. (Come lo posso fare?Posso ridefinire la lunghezza della stringa #?

So usare SomeClass.metaClass. Posso ottenere un riferimento a un metodo esistente e definire un nuovo metodo (o sovrascrivere), ma non riesco a farlo per i metodi Java esistenti.

+0

Questo sarebbe un comportamento scorretto. Potresti essere in grado di usare un metodo 'pad()' che estenderebbe la tua stringa ad una lunghezza massima specificata. Quindi puoi chiamare la lunghezza su quella stringa. – Nate

+0

Cosa ti piace ottenere con quello? Si romperà molto codice in questo modo. –

+0

Perché? Quante cose sei suscettibile di interrompere facendo questo? Posso fare 2 + 2 = 5, ma potrebbe non essere la soluzione migliore. Forse vuoi semplicemente regolare il valore restituito in alcune situazioni speciali? – mickeyf

risposta

2

Sembra possibile tramite la stringa abusingmetaClass. Ma il tentativo che ho fatto finora in console groove non ha portato al risultato atteso:

def oldLength = String.metaClass.length 
String.metaClass.length = { -> 
    return oldLength+10; 
} 

println "hi".length() 

emette la triste 2

Penso che si potrebbe dare un'occhiata a Proxy MetaClass o Delegating metaClass.

+0

Penso che il problema sia legato a questo problema: http://jira.codehaus.org/browse/GROOVY-3493 –

+1

Sembra così, questo funziona: String.metaClass.invokeMethod = {String methodName, args -> println (" ciao ") } " hi ".length() // stampa" ciao " – IttayD

+0

Perché questa risposta è stata accettata quando, per propria ammissione, l'autore non funziona? –

1

Se lo hai ridefinito, funzionerebbe solo con il codice Groovy. Groovy non può cambiare il modo in cui viene eseguito il codice Java.

in Groovy, "hi".length() è grosso modo equivalente a questo Java:

stringMetaClass.invokeMethod("hi","length"); 

Perché Groovy in realtà non chiama direttamente la lunghezza, trucchi metaclasse lavorano in codice Groovy. Ma Java non sa di MetaClass, quindi non c'è modo di farlo funzionare.

+0

sì, per favore, mostrami come farlo per groovy solo – IttayD

4

Utilizzando Groovy, è possibile sostituire qualsiasi metodo (anche quelli delle classi finali) con la propria implementazione. La sostituzione del metodo in Groovy utilizza il protocollo meta-oggetto, non l'ereditarietà.

Ecco l'esempio che avete richiesto, vale a dire come fare String.length() tornare sempre 4

// Redefine the method 
String.metaClass.invokeMethod = { name, args -> 

    def metaMethod = delegate.metaClass.getMetaMethod(name, args) 
    def result = metaMethod.invoke(delegate, args) 

    name == 'length' ? 4 : result 
} 

// Test it 
assert "i_do_not_have_4_chars".length() == 4 
+0

nota ad altri che potrebbero chiedersi perché questo non è stato accettato come una risposta: è stata presentata dopo che ho commentato che questa è la soluzione nella risposta sopra – IttayD

+0

Puoi annullare l'altra risposta e accettarla se ritieni che sia meglio. Basta fare clic sul segno di spunta verde per non accettare. –

Problemi correlati