1. groovy中类,接口等的定义和使用
1.1 类
右键->New->Groovy Class创建一个groovy类,名字是Person。groovy默认所有的类都是public,所以创建完成的class前面没有public进行修饰。
/**
* 1.groovy中默认都是public
* 2.所有的groovy类都默认集成了一个GroovyObject类
* 这是groovy和java中类的区别
*/
class Person {
String name
Integer age
def increaseAge(Integer years) {
this.name += years
}
}
新建一个脚本groovy script,在脚本里面进行Person的使用。
def person = new Person(name: 'android', age: 26)
println "this name is ${person.name}, " +
"thi age is ${person.age}"
输出结果:
this name is android, thi age is 26
在groovy中直接通过.操作符操作的并不是对象的属性,实际上是调用getName()和getAge()方法。无论是直接通过.还是get/set,最终调用的都是get/set方法,这是和java不同的地方。
调用方法形式如下:
person.increaseAge(10)
1.2 接口
右键->New->Groovy Class,类型是Interface,创建一个Interface类型的class。groovy接口和java最大的不同是groovy不允许定义非public类型的方法。
Action.groovy
/**
* 接口不允许定义非public类型的额接口
*/
interface Action {
void eat()
void drink()
void play()
}
Person.groovy
/**
* 1.groovy中默认都是public
* 2.所有的groovy类都默认集成了一个GroovyObject类
* 这是groovy和java中类的区别
*/
class Person implements Action{
String name
Integer age
def increaseAge(Integer years) {
this.name += years
}
@Override
void eat() {
}
@Override
void drink() {
}
@Override
void play() {
}
}
groovy接口除了不定定义非public类型的方法外,其他和java接口使用几乎一样。
1.3 Trait
trait和interface类似,不同之处在于trait可以为方法提供默认的实现,如果不提供默认实现,需要为方法添加abstract关键字修饰。
DefaultAction.groovy:
trait DefaultAction {
abstract void eat()
void play() {
println 'I can play'
}
}
Peroson.groovy
class Person implements DefaultAction{
String name
Integer age
def increaseAge(Integer years) {
this.name += years
}
@Override
void eat() {
}
}
使用Person对象:
def person = new Person(name: 'android', age: 26)
person.play()
输出结果:
this name is android, thi age is 26
I can play
2. groovy中的元编程
所谓元编程,是指编写的代码所执行的时机。
无论在java还是groovy,都会调用其他类的方法。当调用一个类的方法时,编译器会判断类中是否存在这个方法,如果存在就直接调用类中的方法。在java中找不到类方法会直接报错,但是groovy即使类中没有对应的方法,编译也是可以通过的,groovy编译器会尝试从MetaClass查找是否有此方法。如果MetaClass中包含了此方法,就会调用MetaClass中的方法。如果MetaClass也没有对应的方法,groovy编译器会继续判断是否重写了methodMissing()方法,如果重写了,就调用methodMissing()方法。如果没有重写会继续判断是否重写了invokeMethod()方法,如果重写了invokeMethod()方法,就调用该方法,否则抛出MissingMethodException异常,这是一个运行时的异常。可以用下面一幅图进行概括,同样也适用于属性调用。
2.1 基本流程验证
person.groovy
class Person {
String name
Integer age
def increaseAge(Integer years) {
this.name += years
}
def invokeMethod(String name, Object args) {
return "the methos is ${name}, the params is ${args}"
}
def methodMissing(String name, Object args){
return "the methos is ${name} is missing"
}
}
使用person:
def person = new Person(name: 'android', age: 26)
println person.cry()
当没有invokeMethod()和methodMissing()方法时,运行会报出MissingMethodException,当重写了上述2个方法之后,则会按照先后书序调用对应的方法。
2.2 为类动态添加属性
metaClass可以为一个类动态添加属性和方法。
// 为类动态添加一个属性
Person.metaClass.sex = 'male'
def person = new Person(name: 'android', age: 26)
println person.sex
person.sex = 'female'
println "the new sex is: " + person.sex
输出结果:
male
the new sex is: female
2.3 为类动态添加方法
Person.metaClass.sex = 'male'
Person.metaClass.sexUpperCase = { -> sex.toUpperCase()}
def person = new Person(name: 'android', age: 26)
println person.sexUpperCase()
输出结果:
MALE
2.4 为类添加静态方法
Person.metaClass.static.createPerson = {String name, int age ->
new Person(name: name, age: age)
}
def person3 = Person.createPerson("androidtest", 30)
println person3.name + " and " + person3.age
输出结果:
androidtest and 30
2.5 实现全局有效的功能
上面的实现只是针对本模块内有效,模块外部并不会生效,如果想实现全局有效的功能,需要使用调用ExpandoMetaClass.enableGlobally(),让其全局生效。
代码如下:
Person.groovy:
package expand
class Person {
String name
Integer age
def increaseAge(Integer years) {
this.name += years
}
def invokeMethod(String name, Object args) {
return "the methos is ${name}, the params is ${args}"
}
def methodMissing(String name, Object args){
return "the methos is ${name} is missing"
}
}
ApplicationManager.groovy
package expand
/**
* 模拟应用管理类
*/
class ApplicationManager {
static void init() {
ExpandoMetaClass.enableGlobally()
// 为第三方类添加方法
Person.metaClass.static.createPerson = {String name, int age ->
new Person(name: name, age: age)
}
}
}
PersonManager.groovy
package expand
/**
* Person管理类
*/
class PersonManager {
static Person createPerson(String name, int age) {
return Person.createPerson(name, age)
}
}
Entry.groovy
package expand
class Entry {
static void main(def args) {
println '应用程序正在启动...'
//初始化
ApplicationManager.init()
println '应用程序初始化完成...'
def person = PersonManager.
createPerson('renzhiqiang', 26)
println "the person name is ${person.name} " +
"and the age is ${person.age}"
}
}
运行Entry中的main方法,输出结果:
应用程序正在启动...
应用程序初始化完成...
the person name is renzhiqiang and the age is 26