加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy高效编程——动态改变对象的能力

发布时间:2020-12-14 17:07:28 所属栏目:大数据 来源:网络整理
导读:? ? 来源:http://www.blogjava.net/BlueSUN/archive/2007/07/15/130318.html ? Groovy1.1beta-2开始,实现动态改变对象的能力变的十分简单: 一开始,我们有这样一个类: class ?Person?{ ????String?name } 该类的实例都是哑巴,不能说话,作为造物主的我

?

?

来源:http://www.blogjava.net/BlueSUN/archive/2007/07/15/130318.html

?

Groovy1.1beta-2开始,实现动态改变对象的能力变的十分简单:

一开始,我们有这样一个类:

class ?Person?{
????String?name
}


该类的实例都是哑巴,不能说话,作为造物主的我们该完善它们,使它们能自我介绍(添加实例方法)

class ?Person?{
????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()


运行结果:

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


运行结果:

I'm?山风小子
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


运行结果:

I'm?山风小子
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()


运行结果:

I'm?山风小子,?Male
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()


运行结果:

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,? " 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?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()


运行结果:

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
}


运行结果:

I'm?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 " )


运行结果:

{"Leona"}
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


运行结果:

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())


运行结果:

hELLO,?WORLD!
Sun?Jun?08?14:53:28?CST?2008




附:朝花夕拾——Groovy & Grails

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读