從Groovy1.1beta-2開始,實(shí)現(xiàn)動(dòng)態(tài)改變對(duì)象的能力變的十分簡單:
一開始,我們有這樣一個(gè)類:
class?Person?{
????String?name
}
該類的實(shí)例都是啞巴,不能說話,作為造物主的我們該完善它們,使它們能自我介紹
(添加實(shí)例方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
現(xiàn)在讓我們看看,它們到底是否真的能夠開口自我介紹了呢:
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
運(yùn)行結(jié)果:
I'm?山風(fēng)小子
嗯~人類改造成功~
但人應(yīng)該有性別吧,嗯~對(duì)的,加個(gè)性別屬性sex
(添加屬性):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認(rèn)為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
println?person.sex
運(yùn)行結(jié)果:
I'm?山風(fēng)小子
Male
但做男人累啊~為了買房,娶妻拼命賺錢,做女人算了,做變性手術(shù):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認(rèn)為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
println?person.sex
//?做變性手術(shù),變?yōu)榕?Female)
person.sex?=?"Female"
println?person.sex
運(yùn)行結(jié)果:
I'm?山風(fēng)小子
Male
Female
作為造物主的我們考慮到手術(shù)的風(fēng)險(xiǎn)性,為了讓其他人知道自己現(xiàn)在是個(gè)女的,在介紹中添加性別說明:
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認(rèn)為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
//?做變性手術(shù),變?yōu)榕?Female)
person.sex?=?"Female"
person.introduce()
運(yùn)行結(jié)果:
I'm?山風(fēng)小子,?Male
I'm?山風(fēng)小子,?Female
為了造人方便點(diǎn),搞個(gè)工廠方法
(添加類方法,即靜態(tài)方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認(rèn)為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
//?做變性手術(shù),變?yōu)榕?Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點(diǎn)
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風(fēng)小子",?"Male")
bluesun.introduce()
運(yùn)行結(jié)果:
I'm?山風(fēng)小子,?Male
I'm?山風(fēng)小子,?Female
I'm?山風(fēng)小子,?Male
為了方便實(shí)例化Person,添加一個(gè)構(gòu)造方法
(添加構(gòu)造方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認(rèn)為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風(fēng)小子")
person.introduce()
//?做變性手術(shù),變?yōu)榕?Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點(diǎn)
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風(fēng)小子",?"Male")
bluesun.introduce()
//?方便實(shí)例化Person,添加一個(gè)構(gòu)造方法
Person.metaClass.constructor?<<?{?name,?sex?->
????new?Person(name:name,?sex:sex)
}
def?daniel?=?new?Person("Daniel",?"Male")
daniel.introduce()
運(yùn)行結(jié)果:
I'm?山風(fēng)小子,?Male
I'm?山風(fēng)小子,?Female
I'm?山風(fēng)小子,?Male
I'm?Daniel,?Male
最后,引用一個(gè)官方例子swapCase來展示一下Groovy是如何增強(qiáng)既有類的能力的
(演示如何使用delegate,注意演示的是final類:String)String.metaClass.swapCase?=?{->
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當(dāng)前正被‘改造’的對(duì)象
??????delegate.each?{
???????????sb?<<?(Character.isUpperCase(it?as?char)???Character.toLowerCase(it?as?char)?:?
???????????????????Character.toUpperCase(it?as?char))
??????}
??????sb.toString()
}
String?s?=?"Hello,?world!"
println?s.swapCase()
運(yùn)行結(jié)果:
hELLO,?WORLD!
<<用于添加方法(如果方法已經(jīng)存在,會(huì)發(fā)生groovy.lang.GroovyRuntimeException異常),=用于添加方法或覆蓋既有方法
而從Groovy1.1beta-3開始,Groovy的動(dòng)態(tài)性有了進(jìn)一步的增強(qiáng):我們可以通過respondsTo和hasProperty方法來判斷是否存在某個(gè)方法和某個(gè)屬性:
class?Person?{
????String?name
????public?Person(name)?{
????????this.name?=?name
????}
????def?introduce()?{
????????println?"I'm?$name"
????}
????def?introduce(String?name)?{
????????println?"She?is?$name"
????}
}
def?daniel?=?new?Person('Daniel')
//?判斷實(shí)例daniel是否有方法introduce()
if?(daniel.metaClass.respondsTo(daniel,?'introduce'))?{
????daniel.introduce()
}
//?判斷實(shí)例daniel是否有方法introduce(String)
if?(daniel.metaClass.respondsTo(daniel,?'introduce',?String))?{
????daniel.introduce('Annie')
}
//?判斷實(shí)例daniel是否有屬性name
if?(daniel.metaClass.hasProperty(daniel,?'name'))?{
????println?daniel.name
}
運(yùn)行結(jié)果:
I'm?Daniel
She?is?Annie
Daniel
使用methodMissing方法來處理對(duì)那些不存在的方法的調(diào)用class?Person?{
????String?name
????public?Person(name)?{
????????this.name?=?name
????}
????def?introduce()?{
????????println?"I'm?$name"
????}
????def?introduce(String?name)?{
????????println?"She?is?$name"
????}
}
Person.metaClass.methodMissing?=?{?name,?args?->
????//?動(dòng)態(tài)添加方法
????Person.metaClass."$name"?=?{?methodArgs?->
????????if?("hello".equals(name))
????????????println?"$methodArgs"
????????else?{
????????????def?argList?=?Arrays.asList(methodArgs)
????????????println?"No?method?$name?with?${argList*.class}"
????????}
????}
???delegate."$name"(args)
}
def?daniel?=?new?Person('Daniel')
daniel.hello("Leona")
daniel.hi("Annie",?"Leona")
運(yùn)行結(jié)果:
{"Leona"}
No?method?hi?with?[class?java.lang.String,?class?java.lang.String]
類似地,
使用propertyMissing方法來處理對(duì)那些不存在的屬性的引用class?Person?{
????String?name
????public?Person(name)?{
????????this.name?=?name
????}
????def?introduce()?{
????????println?"I'm?$name"
????}
????def?introduce(String?name)?{
????????println?"She?is?$name"
????}
}
Person.metaClass.propertyMissing?=?{?String?name,?value?->
????//?動(dòng)態(tài)添加屬性
????Person.metaClass."$name"?=?value
}
def?daniel?=?new?Person('Daniel')
daniel.sex?=?'Male'
println?daniel.sex
運(yùn)行結(jié)果:
Male
而從Groovy1.6beta-2-snapshot開始,Groovy在這方面的語法更加簡潔了(當(dāng)然原來prototype式的語法也同樣支持):String.metaClass?{
????'static'?{
????????value?=?{
????????????it.toString()
????????}
????}
????
????swapCase?=?{?->
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當(dāng)前正被‘改造’的對(duì)象
??????delegate.each?{
???????????sb?<<?(Character.isUpperCase(it?as?char)???Character.toLowerCase(it?as?char)?:?
???????????????????Character.toUpperCase(it?as?char))
??????}
??????sb.toString()
????}
}
String?s?=?'Hello,?world!'
println?s.swapCase()
println?String.value(new?Date())
運(yùn)行結(jié)果:
hELLO,?WORLD!
Sun?Jun?08?14:53:28?CST?2008
附:
朝花夕拾——Groovy & Grails
posted on 2007-07-15 00:50
山風(fēng)小子 閱讀(4397)
評(píng)論(12) 編輯 收藏 所屬分類:
Groovy & Grails