2011-01-24 8 views
33

Czy można dynamicznie dodać właściwość lub metodę do obiektu Groovy? To, co starałem dotąd:Dynamicznie dodaj właściwość lub metodę do obiektu w groovy

class Greet { 
    def name 
    Greet(who) { name = who[0].toUpperCase() + [1..-1] } 
    def salute() { println "Hello $name!" } 
} 

g = new Greet('world') // create object 
g.salute()    // Output "Hello World!" 

g.bye = { println "Goodbye, $name" } 
g.bye() 

Ale pojawia się następujący wyjątek:

Hello World! 
Caught: groovy.lang.MissingPropertyException: No such property: bye for class: Greet 
Possible solutions: name 
    at test.run(greet.groovy:11) 

Odpowiedz

55

Jeśli chcesz po prostu dodać metodę bye() do jednej instancji g klasy Greet, ty trzeba zrobić:

g.metaClass.bye = { println "Goodbye, $name" } 
g.bye() 

w przeciwnym razie, aby dodać bye() do wszystkich instancji Greet (od teraz), zadzwoń

Greet.metaClass.bye = { println "Goodbye, $name" } 

Ale trzeba by to zrobić przed utworzyć instancję klasy Greet

Here is a page on the per-instance metaClass

And here is the page on MetaClasses in general


Ponadto, nie jest to błąd w konstruktora. Tracisz who z Infront swojej [1..-1] a jeśli konstruktor jest podjęło String mniej niż 2 znaków długości, to wyjątek

lepsza wersja może być:

Greet(String who) { 
    name = who.inject('') { String s, String c -> 
    s += s ? c.toLowerCase() : c.toUpperCase() 
    } 
} 

Jak metioned w komentarzach,

Greet(String who) { 
    name = who.capitalize() 
} 

jest właściwy sposób

+0

To było szybkie! Dzięki! –

+4

Proponuję użyć 'name = who.capitalize()' w konstruktorze. – ataylor

+1

@ataylor Wiedziałem, że będzie lepszy sposób niż "wstrzyknąć"! Pozdrawiam :-) –

Powiązane problemy