? 在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
? 在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
? 在类中还可以定义方法,方法有普通方法和类方法。普通方法要通过类的实例进行调用,类方法可以通过类直接调用。下面在类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
? 在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
}
}
? 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
中间用,
分割。
? 使用运行时元编程,我们可以在运行时截取类和接口的方法。
? 接着我们定义一个类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