来源:http://www.blogjava.net/BlueSUN/archive/2007/07/15/130318.HTML
Groovy1.1beta-2开始,实现动态改变对象的能力变的十分简单:
一开始,我们有这样一个类:
String name
}
该类的实例都是哑巴,不能说话,作为造物主的我们该完善它们,使它们能自我介绍(添加实例方法) :
String name
}
// 添加自我介绍的行为
Person.MetaClass.introduce << {println " I'm $name " }
现在让我们看看,它们到底是否真的能够开口自我介绍了呢:
String name
}
// 添加自我介绍的行为
Person.MetaClass.introduce << {println " I'm $name " }
def person = new Person(name: " 山风小子 " )
person.introduce()
运行结果:
嗯~人类改造成功~
但人应该有性别吧,嗯~对的,加个性别属性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
运行结果:
Male
但做男人累啊~为了买房,娶妻拼命赚钱,做女人算了,做变性手术:
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
运行结果:
Male
Female
作为造物主的我们考虑到手术的风险性,为了让其他人知道自己现在是个女的,在介绍中添加性别说明:
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 山风小子, Female
为了造人方便点,搞个工厂方法(添加类方法,即静态方法) :
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
为了方便实例化Person,添加一个构造方法(添加构造方法) :
String name
}
// 添加自我介绍的行为
Person.MetaClass.introduce << {println " I'm $name " }
// 添加性别属性,默认为男(Male)
Person.MetaClass.sex = " Male "
// 修改之前自我介绍行为,添加性别说明
Person.MetaClass.introduce << {println " I'm $name, " 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 DanIEl, Male
最后,引用一个官方例子swapCase来展示一下Groovy是如何增强既有类的能力的(演示如何使用delegate,注意演示的是final类:String)
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()
运行结果:
<<用于添加方法(如果方法已经存在,会发生groovy.lang.GroovyRuntimeException异常),=用于添加方法或覆盖既有方法
而从Groovy1.1beta-3开始,Groovy的动态性有了进一步的增强:
我们可以通过respondsTo和hasProperty方法来判断是否存在某个方法和某个属性:
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
}
运行结果:
She is AnnIE
DanIEl
使用methodMissing方法来处理 对 那些 不存在的方法的调用
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 " )
运行结果:
No method hi with [class java.lang.String, class java.lang.String]
类似地,使用propertyMissing方法来处理 对 那些 不存在的属性的引用
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
运行结果:
而从Groovy1.6beta-2-snapshot开始,Groovy在这方面的语法更加简洁了(当然原来prototype式的语法也同样支持):
' 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())
运行结果:
Sun Jun 08 14:53:28 CST 2008
附:朝花夕拾——Groovy & Grails
以上是内存溢出为你收集整理的Groovy高效编程——动态改变对象的能力全部内容,希望文章能够帮你解决Groovy高效编程——动态改变对象的能力所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)