文章目录
- 面向对象
- 1 类的定义和对象的定义
- 2 对象的属性值
- 3 方法的定义和调用
- 4 接口
- 5 trait的使用
- 6 元编程方法的调用和拦截
面向对象
1 类的定义和对象的定义
在groovy
中新建一个Student
的类,选择Groovy class
。
Student
类的代码内容如下,在这个类中没有显示定义构造方法:
package com.dream21th.biz//在groovy中所有属性和方法默认都是public
class Student {//定义属性nameString name//定义属性ageint age
}
由于Student
中没有显示定义构造方法,我们在创建该类的对象的时候,可以采用下面方式,具体代码见下面例子:
//创建Student对象,Student类中没有显示定义构造方法,我们依然可以采用下面的方式获取Student对象
def student1 = new Student()
println(student1)//com.dream21th.biz.Student@bee915def student2 = new Student(name: "张三",age: 20)
println(student2)//com.dream21th.biz.Student@3b9fd5def student3 = new Student(name: "李四")
println(student3)//com.dream21th.biz.Student@1dc5318
接下来,我们定义一个Children
类,该类的具体内容如下,不同于上面的Student
类,在该类中显示定义了构造方法。
package com.dream21th.bizclass Children {//定义属性nameString name//定义属性ageint age//显示定义了构造方法Children(String name,int age){this.name=namethis.age=age}
}
由于Children
类中显示定义了构造方法,我们在创建该类的具体对象的时候,可以采用下面的方式:
def children1 = new Children("王五",21)
println(children1)//com.dream21th.biz.Children@116be8bdef children2 = ["赵六",18] as Children
println(children2)//com.dream21th.biz.Children@155d082Children 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.bizclass Children {//定义属性nameString name//定义属性ageint age//显示定义了构造方法Children(String name,int age){this.name=namethis.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.bizinterface MyInterface {//方法一def method1()//方法二def method2(name)
}
接着编一个Animal
类实现MyInterface
接口,具体的代码实现如下:
package com.dream21th.bizclass Animal implements MyInterface {@Overridedef method1() {return "方法一"}@Overridedef method2(Object name) {return "方法二:"+name}
}
5 trait的使用
trait
的使用的方式和java
中的抽象类相似,但是使用的方式和接口很像,用implements
来实现trait
。下面定义一个Car
的抽象类:
package com.dream21th.biztrait Car {//抽象的方法唱歌abstract def sing()//默认的实现的方法def run(){"可以跑"}
}
接着编写一个类FalaLicar
实现Car
的抽象类,重写sing
方法。
package com.dream21th.bizclass FalaLicar implements Car{@Overridedef sing() {return "可以唱歌"}
}
trait
就像抽象类和接口的结合,类实现用implements
关键字来实现,可以实现多个trait
中间用,
分割。
6 元编程方法的调用和拦截
使用运行时元编程,我们可以在运行时截取类和接口的方法。
接着我们定义一个类Person
,代码的信息如下,该类只包含一个drink
方法
class Person {String nameint agedef drink(){"喝酒"}
}
编写测试代码,可以正常的调用drink
方法,但当调用一个不存在的方法say
的时候,出现报错
def person=new Person(name: "张三",age: 18)
person.drink()person.say()
如果不想在调用对象不存在的方法时候报错,可以采用重写invokeMethod
方法的形式来替换不存在的方法,具体的编写代码如下:
package com.dream21th.bizclass Person {String nameint agedef drink(){"喝酒"}@OverrideObject 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.bizclass Person {String nameint agedef drink(){"喝酒"}@OverrideObject 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.bizclass Person {String nameint agedef drink(){"喝酒"}@OverrideObject invokeMethod(String name, Object args) {println("调用invokeMethod方法")return "当前方法:"+name+" 参数:"+args}Object methodMissing(String name, Object args){println("调用methodMissing方法")return "当前方法:"+name+" 参数:"+args}//方便打印@OverrideString 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