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

Groovy高效编程——动态改变对象的能力,第1张

概述    来源: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

总结

以上是内存溢出为你收集整理的Groovy高效编程——动态改变对象的能力全部内容,希望文章能够帮你解决Groovy高效编程——动态改变对象的能力所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1270913.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存