Gradle入门之Groovy元编程

Posted 我就是马云飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle入门之Groovy元编程相关的知识,希望对你有一定的参考价值。

简介

Groovy的元编程是指groovy运行时,可以理解成编写代码所执行的时期,也就是Runtime。在比如有解释执行的Js,编译执行的java,还有运行时期执行的代码java反射。

Groovy运行时的处理逻辑如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i4GhgXKL-1611849711349)(https://s3.ax1x.com/2021/01/14/sdrfyj.png)]

元编程

按照上图所示,我们可以自己写一个Demo,示例代码如下:

class Study 
    public static void main(String[] args) 
        def person = new Personal(name: "Silence", age: 26)
        println(person.printName())
        println(person.printAge())
        println(person.sex)
    


class Personal 
    public String name
    public int age

    public String printName() 
        return "My name is $name"
    

    public String printAge() 
        return "My ag is $age"
    



输出结果如下:

My name is Silence
My ag is 26
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: sex for class: Personal
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:65)
	at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:87)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:329)
	at Study.main(Study.groovy:9)

可以看到前两个日志是正常输出的,第三个控制台则提示MissingPropertyException。也就是上图中,所以逻辑都没进去导致异常输出。

我们在看看如果我们复写invokeMethod方法时的输出效果,代码修改如下:

class Personal 
    public String name
    public int age

    public String printName() 
        return "My name is $name"
    

    public String printAge() 
        return "My ag is $age"
    

    @Override
    Object invokeMethod(String name, Object args) 
        return "this invoke method is $name,this params is $args"
    


控制台输出如下:

My name is Silence
My ag is 26
this invoke method is sex,this params is []

然后我们看看重写methodMissing方法后:

class Personal 
    public String name
    public int age

    public String printName() 
        return "My name is $name"
    

    public String printAge() 
        return "My ag is $age"
    

    @Override
    Object invokeMethod(String name, Object args) 
        return "this invoke method is $name,this params is $args"
    

    Object methodMissing(String name, Object args) 
        return "this Missing method is $name,this params is $args"
    



输出结果如下:

My name is Silence
My ag is 26
this Missing method is sex,this params is []

可以看出,两个方法都重写时,优先调用methodMissing。如果找不到才会调用invokeMethod。

MetaClass

Metaclasses在方法解析中起到核心作用,对于来自groovy代码的每个方法调用,Groovy将找到给定对象的MetaClass,并通过MetaClass#invokeMethod将方法解析委托给Metaclasses,不应该与GroovyObject#invokeMethod混淆,后者恰好是Metaclasses最终可能调用的方法。

注入新字段

现在我们通过metaClass给Personal注入一个新属性看看:

  Personal.metaClass.sex = "男"
  def person = new Personal(name: "Silence", age: 26)
  println(person.printName())
  println(person.printAge())
  println(person.sex)

可以看出我们注入了一个sex的字段,输入结果如下:

My name is Silence
My age is 26

当然了,注入静态变量也是类似,加上static即可。

注入新方法

看到我们输入性别的时候,发现好像和上面对比,不工整,那就自己整一个工整的,修改代码:

        Personal.metaClass.sex = "男"
        Personal.metaClass.printSex =  ->
            "My sex is $sex"
        
        def person = new Personal(name: "Silence", age: 26)
        println(person.printName())
        println(person.printAge())
        println(person.printSex())

输出结果可想而之:

My name is Silence
My age is 26
My sex is 男

这下工整了~。当然了,注入静态方法也是类似,加上static即可。

总结

可以看出,我们可以通过metaClass给类新增变量,新增方法。那么这个和直接在类这种提供有什么区别呢?
举个例子:引入第三方库,其中的某个类有我们想用的方法,但是这个方法又不够全,想给里面添加点自己的方法。通常是extends它进而扩展,但是如果是final 类,任何类不能继承它,只能用它已有的方法。这个时候groovy的动态添加就有了大展身手的地方。不修改、不继承,通过metaclass变相的对原有的类进行了扩展。

参考

groovy中的元编程
Groovy笔记之元编程

本文首发于我的个人博客:Gradle入门之Groovy元编程

更多文章请关注我的公众号:码农职场

以上是关于Gradle入门之Groovy元编程的主要内容,如果未能解决你的问题,请参考以下文章

Gradle入门之Groovy语法

gradle入门之环境安装与配置

Groovy入门

Android Gradle 插件Gradle 构建工具简介 ③ ( Gradle 构建脚本编程语言 | Groovy 语言简介 | Groovy 语言特性 )

Gradle入门--Groovy常用语法

Gradle 之语言基础 Groovy