1、groovy中定义类与方法
class Person {
String name
Integer age
// 定义一个方法
def IncreaseAge(Integer years) { // def定义返回值,返回值类型为Object
this.age += years
}
2、groovy中的Interface与Trait
groovy中的接口与Java中的接口完全相同,实现接口还是使用implement关键字。groovy中的接口只允许定义public类型的方法。
interface Action { // groovy中的接口只允许定义public类型的方法
void eat()
void drink()
void play()
}
trait与接口几乎差不多,不同点是trait可以为方法提供一个默认实现,不提供默认实现,则必须在方法上添加abstract关键字
trait DefaultAction {
abstract void eat() // 如果方法是抽象类型的,则必须在方法上加上abstract关键字
void play() {
println 'i can speak English' // 如果不是抽象类型的方法,则必须为其指定一个默认实现
}
}
3、groovy中方法调用执行的过程
当我们调用类中不存在的方法是,代码在编译时期不会报错,会在代码运行期报错,提示找不到此方法,执行的过程如图所示,但是我们如果不想代码报错,可以重写它的某些方法,当类中不存在某些方法时,使用我们自定义的逻辑,给出温和的提示信息。
3.1、invokeMethod方法
如果调用类中不存在的方法,但我们重写了invokeMethod时,这个时候就会调用invokeMethod,执行里面重写的逻辑,代码不会报错
class Person implements Action{
String name
Integer age
// 定义一个方法
def IncreaseAge(Integer years) { // def定义返回值,返回值类型为Object
this.age += years
}
// 一个方法找不到的时候,会调用他来代替
def invokeMethod(String name, Object args) {
return "the method is ${name}, the params is ${args}"
}
}
3.2、methodMissing方法
当类中不存在调用方法,会执行此方法,而invokeMethod因为是在下一层的判断逻辑中,因此就不会执行invokeMethod,直接执行methodMissing方法然后程序就结束了。
优先级高于invokeMethod
class Person implements Action{
String name
Integer age
// 定义一个方法
def IncreaseAge(Integer years) { // def定义返回值,返回值类型为Object
this.age += years
}
// 优先级高于invokeMethod
def methodMissing(String name, Object args) {
return "the method ${name} is missing"
}
}
4、metaClass方法
该方法可以动态的为类添加属性与方法,十分的强大
使用方式
类名.metaClass.属性名(方法名)= 值 (或者闭包)
4.1、为类动态的添加属性
// 为类动态的添加属性
Person.metaClass.sex = 'male'
def person = new Person(name: '张三', age: 34)
println person.sex
// 如果想要修改设置前面注入的值
person.sex = 'female'
println person.sex
4.2、为类动态的添加方法
添加方法需要借助闭包
Person.metaClass.sexUpperCase = { -> sex.toUpperCase() }
def person2 = new Person(name: '张三', age: 34)
println person2.sexUpperCase() // 调用注入类中的方法
4.3、类添加静态方法
注入静态方法与动态方法的不同点就是,在注入的方法名之前先使用static关键字进行修饰
Person.metaClass.static.CraetPerson = {
println "99999999999"
}
// 调用静态方法
Person.CraetPerson()
注意:注入的属性和方法,只能在当前的脚本类中使用,不能在其它新的脚本类中调用我们自己注入的属性和方法,如果想要在全局的进行使用,可以在当前脚本类中设置此属性 ExpandoMetaClass.enableGlobally()