Groovy面向对象的使用及元编程方法的调用和拦截

发布时间:2024年01月02日

面向对象

1 类的定义和对象的定义

? 在groovy中新建一个Student的类,选择Groovy class

在这里插入图片描述

? Student类的代码内容如下,在这个类中没有显示定义构造方法:

package com.dream21th.biz

//在groovy中所有属性和方法默认都是public
class Student {

    //定义属性name
    String name

    //定义属性age
    int age
}

? 由于Student中没有显示定义构造方法,我们在创建该类的对象的时候,可以采用下面方式,具体代码见下面例子:

//创建Student对象,Student类中没有显示定义构造方法,我们依然可以采用下面的方式获取Student对象
def student1 = new Student()
println(student1)//com.dream21th.biz.Student@bee915

def student2 = new Student(name: "张三",age: 20)
println(student2)//com.dream21th.biz.Student@3b9fd5

def student3 = new Student(name: "李四")
println(student3)//com.dream21th.biz.Student@1dc5318

? 接下来,我们定义一个Children类,该类的具体内容如下,不同于上面的Student类,在该类中显示定义了构造方法。

package com.dream21th.biz

class Children {

    //定义属性name
    String name

    //定义属性age
    int age

    //显示定义了构造方法
    Children(String name,int age){
        this.name=name
        this.age=age
    }
}

? 由于Children类中显示定义了构造方法,我们在创建该类的具体对象的时候,可以采用下面的方式:

def children1 = new Children("王五",21)
println(children1)//com.dream21th.biz.Children@116be8b

def children2 = ["赵六",18] as Children
println(children2)//com.dream21th.biz.Children@155d082

Children children3 = ["王八",28]
println(children3)//com.dream21th.biz.Children@5ecce3
2 对象的属性值

? 在Groovy的对象中,可以通过对象.属性直接获取值,也可以通过get属性的方式拿到对象的值,两种方式的底层调用的都是get方法;同样的原理在给对象的属性赋值的时候可以直接通过对象.属性=值来赋值,也可以通过set属性的方式对对象的属性进行赋值,两种方式的底层调用的都是set方法。在下面的例子中可以看到两种方式的使用:

def children1 = new Children("王五",21)
println(children1)//com.dream21th.biz.Children@116be8b

//可以采用下面两种方式获取对象的属性
printf("姓名:%s,年龄:%d\n",children1.getName(),children1.getAge())//姓名:王五,年龄:21
printf("姓名:%s,年龄:%d\n",children1.name,children1.age)//姓名:王五,年龄:21

//可以通过下面两种方式给对象赋值
children1.name="王五六"
children1.setAge(21)
printf("姓名:%s,年龄:%d\n",children1.name,children1.age)//姓名:王五六,年龄:21
3 方法的定义和调用

? 在类中还可以定义方法,方法有普通方法和类方法。普通方法要通过类的实例进行调用,类方法可以通过类直接调用。下面在类Children中定义三个方法,前面两个是对象方法,最后一个是类方法。

package com.dream21th.biz

class Children {

    //定义属性name
    String name

    //定义属性age
    int age

    //显示定义了构造方法
    Children(String name,int age){
        this.name=name
        this.age=age
    }

    //def相当于Object
    //groovy默认方法最后一句为返回值,return可以省略
    def hello(){
        "my name is " + this.name
    }

    def play(a , b, c){
        "play " +a +" "+ b +" "+ " "+c
    }

    static def say(){
        "say"
    }
}

? 注意:groovy默认方法最后一句为返回值,return可以省略。

? 通过下面的代码编写进行测试:

Children children4 = ["胡八一",28]
println(children4.hello())//my name is 胡八一
println(children4.play("篮球","足球","羽毛球"))//play 篮球 足球  羽毛球
println(Children.say())//say 类方法,通过类直接调用

? 在调用方法的时候,传入参数可以在()里面输入,也可以不要(),直接在方法名后面加参数,多个参数中间用,分割:

def result = children4.play "篮球","足球","羽毛球"
println(result)//play 篮球 足球  羽毛球

? 我们接着编写一个带闭包的方法,具体的方法定义如下,可以在通过闭包中的函数的传入,作为不同的计算:

 //计算值
    def cal(int num1, int num2 ,Closure closure){
        closure.call(num1, num2)
    }
//加法运算
def res=children4.cal(1,3,{a,b -> a+b})
println(res)//4
//乘法运算
def res1=children4.cal(1,3,{a,b -> a*b})
println(res1)//3
4 接口

? 在Groovy中也可以定义接口,和java代码一样,在接口中不能定义非public类型的方法,下面编写一个接口MyInterface:

package com.dream21th.biz


interface MyInterface {
    //方法一
    def method1()

    //方法二
    def method2(name)
}

? 接着编一个Animal类实现MyInterface接口,具体的代码实现如下:

package com.dream21th.biz

class Animal implements MyInterface {
    @Override
    def method1() {
        return "方法一"
    }

    @Override
    def method2(Object name) {
        return "方法二:"+name
    }
}
5 trait的使用

? trait的使用的方式和java中的抽象类相似,但是使用的方式和接口很像,用implements来实现trait。下面定义一个Car的抽象类:

package com.dream21th.biz

trait Car {

    //抽象的方法唱歌
    abstract def sing()

    //默认的实现的方法
    def run(){
        "可以跑"
    }
}

? 接着编写一个类FalaLicar实现Car的抽象类,重写sing方法。

package com.dream21th.biz

class FalaLicar  implements Car{
    @Override
    def sing() {
        return "可以唱歌"
    }
}

? trait就像抽象类和接口的结合,类实现用implements关键字来实现,可以实现多个trait中间用,分割。

6 元编程方法的调用和拦截

? 使用运行时元编程,我们可以在运行时截取类和接口的方法。

在这里插入图片描述

? 接着我们定义一个类Person,代码的信息如下,该类只包含一个drink方法

class Person {

    String name
    int age

    def drink(){
        "喝酒"
    }
}

? 编写测试代码,可以正常的调用drink方法,但当调用一个不存在的方法say的时候,出现报错

def person=new Person(name: "张三",age: 18)
person.drink()

person.say()

在这里插入图片描述

? 如果不想在调用对象不存在的方法时候报错,可以采用重写invokeMethod方法的形式来替换不存在的方法,具体的编写代码如下:

package com.dream21th.biz

class Person {

    String name
    int age

    def drink(){
        "喝酒"
    }

    @Override
    Object invokeMethod(String name, Object args) {
        println("调用invokeMethod方法")
        return "当前方法:"+name+" 参数:"+args
    }
}

? 运行下面代码,可以看到当调用对象不存在的方法的时候会触发invokeMethod的内容

def person=new Person(name: "张三",age: 18)
person.drink()

person.say()

? 如果重写methodMissing方法,那么调用的方法不存在的时候,会触发该方法:

package com.dream21th.biz

class Person {

    String name
    int age

    def drink(){
        "喝酒"
    }

    @Override
    Object invokeMethod(String name, Object args) {
        println("调用invokeMethod方法")
        return "当前方法:"+name+" 参数:"+args
    }

    Object methodMissing(String name, Object args){
        println("调用methodMissing方法")
        return "当前方法:"+name+" 参数:"+args
    }
}

? 我们还可以使用元编程的方式在运行时注入合成类和接口的方法,还是上面的类Person,我们重写toString方法,主要是方便打印查看。

package com.dream21th.biz

class Person {

    String name
    int age

    def drink(){
        "喝酒"
    }

    @Override
    Object invokeMethod(String name, Object args) {
        println("调用invokeMethod方法")
        return "当前方法:"+name+" 参数:"+args
    }

    Object methodMissing(String name, Object args){
        println("调用methodMissing方法")
        return "当前方法:"+name+" 参数:"+args
    }

    //方便打印
    @Override
    String toString() {
        return "name:"+this.name+" age:"+this.age+" sex:"+this.sex
    }
}

? 编写代码动态添加属性sex和动态添加方法setNameUpper

//动态添加属性
Person.metaClass.sex="女"

def person1= new Person(name: "里斯",age: 18)
person1.sex="男"
println(person1)//name:里斯 age:18 sex:男

//动态添加方法
Person.metaClass.setNameUpper={-> name.toUpperCase()}
def person2= new Person(name: "wangming",age: 18)
println(person2.setNameUpper())//WANGMING
文章来源:https://blog.csdn.net/qq_36305027/article/details/135347123
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。