First they ignore you
          then they ridicule you
          then they fight you
          then you win
              -- Mahatma Gandhi
          Chinese => English     英文 => 中文             
          隨筆-221  評論-1047  文章-0  trackbacks-0
          從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?山風小子,?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()

          運行結果:
          I'm?山風小子,?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()

          運行結果:
          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
          posted on 2007-07-15 00:50 山風小子 閱讀(4398) 評論(12)  編輯  收藏 所屬分類: Groovy & Grails
          主站蜘蛛池模板: 海城市| 阳东县| 米林县| 凯里市| 淮安市| 沽源县| 香港 | 铜鼓县| 旺苍县| 南涧| 富锦市| 永州市| 镶黄旗| 建始县| 平昌县| 黄陵县| 高阳县| 洮南市| 武穴市| 焦作市| 潢川县| 贵阳市| 株洲市| 无锡市| 兴安盟| 雷山县| 水富县| 昭平县| 莲花县| 洮南市| 荆州市| 东丽区| 乐业县| 唐海县| 武夷山市| 临沧市| 克什克腾旗| 商丘市| 湘乡市| 清镇市| 琼海市|