Android Gradle学习系列(三)-核心语法讲解与实战之面向对象详解

前言

这一篇我们主要讲解Groovy基础语法的最后一部分面向对象,我们将从以下几个部分来讲解

Groovy类、接口等的定义和使用

这一部分和我们的Java基本没有什么变化,我们首先创建一个Person类,给它指定两个属性nameage,同时在Person类里面定义一个方法increaseAge

/**
 * 1.Groovy中默认都是public
 */
class Person {

    String name
    Integer age

    def increaseAge(Integer years) {
        this.age += years
    }
}

这里在定义的时候要注意,在Groovy中默认都是public类型的,还有就是我们在定义属性的时候用基本类型和用对应的包装类型是一样的,这个我们在之前说过

接着我们创建一个脚本来使用下我们定义好的这个类
在这里插入图片描述
这里有个地方要和Java做下区分,在Java中,我们直接使用类名.属性,调用的是这个类的成员变量,但是在Groovy中我们使用类名.属性相当于调用这个属性对应的get/set方法

类我们说完了,接下来我们定义一个接口,这个几乎和Java没有任何区别

interface Action {

    void eat()

    void drink()

    void play()

}

然后让我们的Person类实现这个接口即可

/**
 * 1.Groovy中默认都是public
 */
class Person implements Action {

    String name
    Integer age

    def increaseAge(Integer years) {
        this.age += years
    }

    @Override
    void eat() {

    }

    @Override
    void drink() {

    }

    @Override
    void play() {

    }
}

Groovy中有一个Java中没有的类型trait,它其实和我们Java中的抽象类差不多
在这里插入图片描述

trait DefaultAction {
    
    abstract void eat()

    void play() {
        println ' i can play.'
    }
}

使用的方式和接口一样,用implements关键字,它相当于Java中的接口和抽象类的结合

Groovy的元编程

在这里插入图片描述
我们首先来看下这个流程图,顺序从上往下,这个流程图适用于方法和属性,我们以方法为例
首选我们调用一个类中的方法,编译器会判断类中是否由此方法,如果是,直接调用我们类中的这个方法,这个和我们的Java是一样的,但是Java中却没有否这种情况,在Java中如果在类中找不到,编译器就会在编译期报错,但是在Groovy中也会编译通过的,先去MetaClass中看看有没有这个方法,有的话直接调用.没有的话就看看类中是否重写了methodMissing(String name, Object args)方法,然后在看看是否重写了类中的invokeMethod(String name, Object args)方法,都不满足的话才抛出一个异常,接下来我们就来验证下这个流程

我们还是使用我们之前定义的那个Person类,我们调用一下这个类里面没有的方法
在这里插入图片描述
直接报错了,对不对,因为我们这里并不满足上面流程图里面的任何一种情况,接下来我们就对着流程图来分别满足下其中的某一种情况,这里我们从下往上来实现

1、重写invokeMethod

我们在Person类中重写这个方法
在这里插入图片描述
然后我们重新运行下
在这里插入图片描述
我们看见没报错,并且打印出来的就是我们刚才重写的invokeMethod里面的返回值

2.定义methodMissing方法

在这里插入图片描述
看下打印结果
在这里插入图片描述

我们看见,即使我们把两个方法都定义了一遍,但是打印出来的确是methodMissing的返回值,说明它的优先级是高于invokeMethod()

3、MetaClass

GroovyMetaClass允许在运行时为行为和状态分配行为和状态,而无需编辑原始的源代码。这是Groovy用来扩展Java JDK对象的机制,我们可以使用MetaClass为类在运行时动态添加 属性 和 方法,我们接下来通过几个例子讲解下

3.1 为类动态添加一个属性

在这里插入图片描述

3.2 为类动态添加方法

在这里插入图片描述

3.3 为类动态添加静态方法

在这里插入图片描述

好了,通过上面的例子我们知道Groovy中的MetaClass很强大,对于一些第三方的扩展使用MetaClass居很方便,但是它使用的时候有限制,作用域不是全局,只在当前类中生效,比如我们在A中为Person动态增加了一个属性sex,我们想在B中使用是不可行的,我们通过实际例子验证下
在这里插入图片描述
在这里插入图片描述

我们看见在MetaClassB中打印Personsex属性就会报错,那这个怎么解决呢?

  • 第一种:在MetaClassB中再使用MetaClass动态注入一次属性和方法。
  • 第二种: 使用ExpandoMetaClass.enableGlobally()方法

第一种没啥好说的,和我们之前讲解的一样即可,我们主要说下第二种方式
首选我们创建一个类Entry表明我们的应用程序入口

class Entry {
    static void main(def args) {
    }
}

之后我们创建一个类ApplicationManager,这个类表示整个应用管理类,我们的初始话工作就在这个类里面

class ApplicationManager {

    static void init() {
        ExpandoMetaClass.enableGlobally()
        //为第三方类添加方法
        Person.metaClass.static.createPerson = { String name, int age ->
            new Person(name: name, age: age)
        }
    }
}

我们在init方法里面完成对Person的扩展,为其添加一个createPerson的静态方法,之后我们创建Person都可以根据这个方法来创建,为了统一我们在建一个Person管理类

/**
 * Person管理类
 */
class PersonManager {
    static Person createPerson(String name, int age) {
        return Person.createPerson(name, age)

    }
}

准备工作都做完了,我们在我们的入口类里面验证下

class Entry {
    static void main(def args) {
        println '应用程序正在启动...'
        ApplicationManager.init()
        println '应用程序初始化完成...'

        def person = PersonManager.createPerson('Greathfs', 18)
        println "the person name is ${person.name} , the person age is ${person.age}"
    }
}

我们运行下看看结果
在这里插入图片描述
我们看到我们并没有调用我们Person的构造方法,但是依旧创建成功了,说明这个方法全局都生效

发布了87 篇原创文章 · 获赞 319 · 访问量 149万+

猜你喜欢

转载自blog.csdn.net/Greathfs/article/details/102925601