一開始,我們有這樣一個類:
class?Person?{
????String?name
}
????String?name
}
該類的實例都是啞巴,不能說話,作為造物主的我們該完善它們,使它們能自我介紹(添加實例方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
現在讓我們看看,它們到底是否真的能夠開口自我介紹了呢:
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
運行結果:
I'm?山風小子
嗯~人類改造成功~
但人應該有性別吧,嗯~對的,加個性別屬性sex(添加屬性):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風小子")
person.introduce()
println?person.sex
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風小子")
person.introduce()
println?person.sex
運行結果:
I'm?山風小子
Male
Male
但做男人累啊~為了買房,娶妻拼命賺錢,做女人算了,做變性手術:
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風小子")
person.introduce()
println?person.sex
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
println?person.sex
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
def?person?=?new?Person(name:"山風小子")
person.introduce()
println?person.sex
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
println?person.sex
運行結果:
I'm?山風小子
Male
Female
Male
Female
作為造物主的我們考慮到手術的風險性,為了讓其他人知道自己現在是個女的,在介紹中添加性別說明:
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
運行結果:
I'm?山風小子,?Male
I'm?山風小子,?Female
I'm?山風小子,?Female
為了造人方便點,搞個工廠方法(添加類方法,即靜態方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風小子",?"Male")
bluesun.introduce()
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風小子",?"Male")
bluesun.introduce()
運行結果:
I'm?山風小子,?Male
I'm?山風小子,?Female
I'm?山風小子,?Male
I'm?山風小子,?Female
I'm?山風小子,?Male
為了方便實例化Person,添加一個構造方法(添加構造方法):
class?Person?{
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風小子",?"Male")
bluesun.introduce()
//?方便實例化Person,添加一個構造方法
Person.metaClass.constructor?<<?{?name,?sex?->
????new?Person(name:name,?sex:sex)
}
def?daniel?=?new?Person("Daniel",?"Male")
daniel.introduce()
????String?name
}
//?添加自我介紹的行為
Person.metaClass.introduce?<<?{println?"I'm?$name"}
//?添加性別屬性,默認為男(Male)
Person.metaClass.sex?=?"Male"
//?修改之前自我介紹行為,添加性別說明
Person.metaClass.introduce?<<?{println?"I'm?$name,?$sex"}
def?person?=?new?Person(name:"山風小子")
person.introduce()
//?做變性手術,變為女的(Female)
person.sex?=?"Female"
person.introduce()
//?工廠方法,造人方便點
Person.metaClass.'static'.createPerson?=?{?name,?sex?->
????Person?p?=?new?Person()
????p.name?=?name
????p.sex?=?sex
????return?p
}
def?bluesun?=?Person.createPerson("山風小子",?"Male")
bluesun.introduce()
//?方便實例化Person,添加一個構造方法
Person.metaClass.constructor?<<?{?name,?sex?->
????new?Person(name:name,?sex:sex)
}
def?daniel?=?new?Person("Daniel",?"Male")
daniel.introduce()
運行結果:
I'm?山風小子,?Male
I'm?山風小子,?Female
I'm?山風小子,?Male
I'm?Daniel,?Male
I'm?山風小子,?Female
I'm?山風小子,?Male
I'm?Daniel,?Male
最后,引用一個官方例子swapCase來展示一下Groovy是如何增強既有類的能力的(演示如何使用delegate,注意演示的是final類:String)
String.metaClass.swapCase?=?{->
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當前正被‘改造’的對象
??????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()
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當前正被‘改造’的對象
??????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()
運行結果:
hELLO,?WORLD!
<<用于添加方法(如果方法已經存在,會發生groovy.lang.GroovyRuntimeException異常),=用于添加方法或覆蓋既有方法
而從Groovy1.1beta-3開始,Groovy的動態性有了進一步的增強:
我們可以通過respondsTo和hasProperty方法來判斷是否存在某個方法和某個屬性:
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')
//?判斷實例daniel是否有方法introduce()
if?(daniel.metaClass.respondsTo(daniel,?'introduce'))?{
????daniel.introduce()
}
//?判斷實例daniel是否有方法introduce(String)
if?(daniel.metaClass.respondsTo(daniel,?'introduce',?String))?{
????daniel.introduce('Annie')
}
//?判斷實例daniel是否有屬性name
if?(daniel.metaClass.hasProperty(daniel,?'name'))?{
????println?daniel.name
}
????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')
//?判斷實例daniel是否有方法introduce()
if?(daniel.metaClass.respondsTo(daniel,?'introduce'))?{
????daniel.introduce()
}
//?判斷實例daniel是否有方法introduce(String)
if?(daniel.metaClass.respondsTo(daniel,?'introduce',?String))?{
????daniel.introduce('Annie')
}
//?判斷實例daniel是否有屬性name
if?(daniel.metaClass.hasProperty(daniel,?'name'))?{
????println?daniel.name
}
運行結果:
I'm?Daniel
She?is?Annie
Daniel
She?is?Annie
Daniel
使用methodMissing方法來處理對那些不存在的方法的調用
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?->
????//?動態添加方法
????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")
????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?->
????//?動態添加方法
????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")
運行結果:
{"Leona"}
No?method?hi?with?[class?java.lang.String,?class?java.lang.String]
No?method?hi?with?[class?java.lang.String,?class?java.lang.String]
類似地,使用propertyMissing方法來處理對那些不存在的屬性的引用
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?->
????//?動態添加屬性
????Person.metaClass."$name"?=?value
}
def?daniel?=?new?Person('Daniel')
daniel.sex?=?'Male'
println?daniel.sex
????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?->
????//?動態添加屬性
????Person.metaClass."$name"?=?value
}
def?daniel?=?new?Person('Daniel')
daniel.sex?=?'Male'
println?daniel.sex
運行結果:
Male
而從Groovy1.6beta-2-snapshot開始,Groovy在這方面的語法更加簡潔了(當然原來prototype式的語法也同樣支持):
String.metaClass?{
????'static'?{
????????value?=?{
????????????it.toString()
????????}
????}
????
????swapCase?=?{?->
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當前正被‘改造’的對象
??????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())
????'static'?{
????????value?=?{
????????????it.toString()
????????}
????}
????
????swapCase?=?{?->
??????def?sb?=?new?StringBuffer()
??????//?delegate與this類似,引用當前正被‘改造’的對象
??????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())
運行結果:
hELLO,?WORLD!
Sun?Jun?08?14:53:28?CST?2008
Sun?Jun?08?14:53:28?CST?2008
附:朝花夕拾——Groovy & Grails