Groovy 之 面向对象

简介: Groovy 之 面向对象

对象


首先创建一个 Person 类


class Person {
    String name;
    Integer age;
    /**
     * 定义方法 ,def 代表的就是 object
     * @param years
     */
    def increateAge(Integer years) {
        this.age += years;
}


上面我们定义了一个 Person 类,注意他和 java 类还是有所不同的。区别如下:


1,groovy 中的所有类 都继承自 GroovyObject


2,groovy 中的所有 class ,方法等都是 public 类型的


接着看一下使用:


def Person person = new Person(name: "张三", age: 20);
println "the name is ${person.name} , the age is ${person.age}"


尽管没有构造方法,但是在 groovy 中依然可以进行赋值,而且是想给那个就给那个赋值


还有一点要注意:最后一行的打印语句使用的是 .name 和 .age , 在 groovy 中,无论直接使用 . 字段或者是 get / set 方法,最终调用的都是 get / set 。


接口


首先定义一个接口


interface Action {
    void eat()
    void drink()
    void play()
}


其实这和 java 中的接口基本一样,没有多大区别 。但是需要注意的是在 groovy 中定义的接口方法不能是 protected 类型的。其他的基本都一样


trait


我感觉 trait 是介于接口和抽象之间的。他内部可以定义抽象方法,也可以定义具体的实现方法。如下:


trait DefaultAction {
    //抽象类型
    abstract void eat()
    //空实现
    void pay() {
        println 'i can pay'
    }
}


如果你有一个接口,接口中的方法非常多。而实现类只用到了一个特定的方法,这种情况就会造成代码非常臃肿,这种情况就可以使用 trait。只需要将特定的方法抽象即可其他的默认实现即可。


元编程


说白了就是运行时期的一个策略。例如调用一个对象的某一个方法,如果这个方法不存在,编译器也不会报错,而是通过一系列的查找最终确定是调用还是抛出异常,下面就是简化后的流程:


0a2653c851af460fa595bd959398a8f1.png


这里我们来实现一下这个过程,我们从底部往上看,这样比较简单,首先还是一个 Person类:


class Person {
    String name;
    Integer age;
}


这里并没有任何方法,我们创建一个对象,并调用一个不存在的方法,如下:


def Person person = new Person(name: "张三", age: 205);
person.cry()


调用 cry 方法后编译器没有任何报错,但是运行时会报错如下:


Caught: groovy.lang.MissingMethodException: No signature of method: variable.Person.cry()


下面在 Person 中重写一个方法 invokeMethod ,如下:


/**
 * 一个方法找不到时 ,会调用这个方法
 * @param name
 * @param Object
 * @return
 */
def invokeMethod(String name, Object) {
        println "the name is ${name} , the age is ${age}";
}


接着在运行一下:


the name is cry , the age is 205


就会发现没有报错,虽然没有 cry 方法,但是 invokMethod 方法被执行了。当某个方法找不到的时候这个方法就会被执行。


接着继续重写一个方法:methodMissing


/**
     * 比 invokeMethod 优先级高,如果重写了此方法,则 invokeMethod 不会调用
     * @param name
     * @param args
     * @return
     */
    def methodMissing(String name, Object args) {
        println "this missing ${name}"
    }


结果如下:


this missing cry


这个方法会在 invokeMethod 之前执行,如果执行这个方法,invokeMethod 不会被带调用,这个方法在 倒着第二层


MetaClass


metaClass 元类,通过它我们可以给某一个类动态的添加字段,方法,静态方法。下面分别实现一些


动态添加属性


Person.metaClass.sex = 'male' //添加属性
def Person per = new Person(name: "张三", age: 205);
per.sex = 'female'
println "the new sex is:" + per.sex;
//结果:the new sex is:female


动态添加方法


//添加属性
Person.metaClass.sex = 'male'
//为类动态的添加方法
Person.metaClass.sexUpperCase = {
    ->
    //将 sex 转为大写,这个方法 String 中的方法
    sex.toUpperCase()
}
def Person per = new Person(name: "张三", age: 205);
//调用动态添加的方法
println per.sexUpperCase()
//结果:MALE


动态添加静态方法


Person.metaClass.static.createPerson = {
    String name, Integer age ->
      //创建对象
        return new Person(name: name, age: age)
}
Person pe = Person.createPerson("张三",20)
println pe.name + "----" + pe.age
//结果 :张三----20


通过这种动态的注入有什么好处呢:例如你你使用了某个第三方库,想要添加某些方法,这个时候就可以使用这种方法来实现,而不用新建一个类去继承他。特别是某些类被修饰为 final ,那我们更不可能去修改他的内容了。但是通过这种方法可以,如下:


//注意,这里需要初始化一下,否则无法确定其类型
String.metaClass.lv = '';
String string = "String"
string.lv = "我是自定义属性"
println string.lv
//结果:我是自定义属性


当然,这个动态创建的方法等都不是全局的,在别的类中如果用就需要重新注入。的确,groovy 提供了设置全局的方法,下面通过一个例子来看一下:


首先,还是一个 Person 类。


class Person {
    String name;
    Integer age;
}


接着是 PersonManager 类


/**
 * PerSon 管理类
 */
class PersonManager {
    static Person createPerson(String name, int age) {
        //调用 Person 不存在的方法
        return Person.createPerson(name, age)
    }
}


上面调用一个不存在的方法。


class ApplicationManager {
    static void init() {
        //设置全局
        ExpandoMetaClass.enableGlobally()
        //创建 Person 静态方法
        Person.metaClass.static.createPerson = {
            String name, Integer age ->
                return new Person(name: name, age: age)
        }
    }
}


在 init 方法中设置全局,动态注入了一个静态方法,获取 Person 对象。最后看一下使用:


class Entry {
    public static void main(String[] args) {
        println '应用程序正在启动'
        //初始化
        ApplicationManager.init()
        println '应用程序初始化完成'
        def person = PersonManager.createPerson("张三", 20)
        println person.name + "----" + person.age
    }
}


最终结果如下:


应用程序正在启动

应用程序初始化完成

张三----20


可以看到通过动态注入的静态方法创建了 Person 对象


plicationManager.init()
println ‘应用程序初始化完成’
    def person = PersonManager.createPerson("张三", 20)
    println person.name + "----" + person.age
}


最终结果如下:


```java

应用程序正在启动

应用程序初始化完成

张三----20


可以看到通过动态注入的静态方法创建了 Person 对象


相关文章
|
16天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
8253 19
|
15天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
2608 14
|
14天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1881 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
13天前
|
人工智能 编解码 并行计算
MiniMax-H3 一键整合包技术文档:8G 显存运行 AI 漫剧制作 —— 角色替换 / 动作迁移 / 文图生视频部署与调参指南
MiniMax H3 是 MiniMax 开源的全模态视频生成模型,支持文/图/音/视多条件输入,输出最高2K、15秒带双声道音频视频。本文档详述其Int8量化版在8GB显存下的本地一键部署、三段式工作流(EDIT/REPLACE/CONTINUE)、参数调优及常见问题排查。(239字)
|
9天前
|
人工智能 Linux 开发者
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
Codex是OpenAI推出的AI编程智能体,可读取本地项目、理解需求并自动修改代码。支持桌面GUI、命令行(CLI)及VS Code/Cursor插件三种形态,覆盖可视化操作、终端高效开发与编辑器无缝集成场景,助开发者用自然语言驱动编码全流程。(239字)
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
|
9天前
|
人工智能 JSON 编解码
【2026最新版】ComfyUI本地部署教程,新手也能看懂!
ComfyUI是本地运行的AI绘画工具,采用节点式工作流设计:通过拖拽连接“加载模型”“提示词编码”“采样”“解码”等模块,实现高度可控的文生图。新手推荐使用秋叶整合包,一键启动、内置模型管理与插件安装器,轻松上手。(239字)
|
23天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
2491 1

热门文章

最新文章