前面说到groovy支持脚本和类,前面一节已将简单说了脚本和类之间的关系,这一节主要介绍一下groovy中类的相关知识,即面向对象相关知识。html
groovy中支持的原始数据类型与java相同,分别是boolean,char,short,int,long,float,double。java
groovy中的类与java中很类似,但有如下几点是groovy特有的:windows
public
修饰的字段会被自动转换成属性变量,这样能够避免不少冗余的get和set方法。groovy的普通类和java相似,使用new关键字得到实例。闭包
内部类也基本相似,下面给一个例子:ui
class Outer2 { private String privateStr = 'some string' def startThread() { new Thread(new Inner2()).start() } class Inner2 implements Runnable { void run() { println "${privateStr}." } } }
抽象类也与java基本相似:this
abstract class Abstract { String name abstract def abstractMethod() def concreteMethod() { println 'concrete' } }
groovy的接口和java也基本相似,支持接口继承接口。操作系统
groovy的构造方法和java就有略微不一样了,groovy的构造方法支持位置参数
和命名参数
,下面具体看。code
位置构造参数跟java中的一般构造方法相似,不一样位置的参数具备不一样的含义。以下:htm
class PersonConstructor { String name Integer age PersonConstructor(name, age) { this.name = name this.age = age } } def person1 = new PersonConstructor('Marie', 1) def person2 = ['Marie', 2] as PersonConstructor PersonConstructor person3 = ['Marie', 3]
具体调用构造方法的时候groovy多了两种写法。由于位置已经固定,因此即便PersonConstructor person3 = ['Marie', 3]
这样的写法groovy也能从内部给你作初始化。对象
命名参数构造方法不须要用户定义,当一个类没有构造方法的时候,其默认有一个命名参数构造方法。
class PersonWOConstructor { String name Integer age } def person4 = new PersonWOConstructor() def person5 = new PersonWOConstructor(name: 'Marie') def person6 = new PersonWOConstructor(age: 1) def person7 = new PersonWOConstructor(name: 'Marie', age: 2)
定义groovy的方法也很简单,可以使用关键字def
或者返回值就行。groovy中的方法都有返回值,若是没有写return
语句,groovy会计算方法中的最后一行语句并将其结果返回。
下面是四种不一样的方法定义:
def someMethod() { 'method called' } String anotherMethod() { 'another method called' } def thirdMethod(param1) { "$param1 passed" } static String fourthMethod(String param1) { "$param1 passed" }
在自定义的方法中要使用命名参数的话,就要使用Map做为惟一参数,以下:
def foo(Map args) { "${args.name}: ${args.age}" } foo(name: 'Marie', age: 1)
groovy方法支持默认参数,这样就是的其参数变得可选,当参数没有被填入,则会使用默认参数:
def foo(Map args) { "${args.name}: ${args.age}" } foo(name: 'Marie', age: 1)
这个在java中也是存在的,举个简单的例子:
def foo(Map args) { "${args.name}: ${args.age}" } foo(name: 'Marie', age: 1)
groovy中的注解跟java中的相似,但又比java中多了一些特性,下面简单介绍一下。
在groovy中,有一个有趣的语言特性就是能够使用闭包
做为注解的参数值。这样的注解通常在什么状况下使用呢?举个简单的例子,有些时候软件的运行时依赖其运行的环境和操做系统的,针对不一样的环境或系统,表现也不同。看一下这个例子:
class Tasks { Set result = [] void alwaysExecuted() { result << 1 } @OnlyIf({ jdk>=6 }) void supportedOnlyInJDK6() { result << 'JDK 6' } @OnlyIf({ jdk>=7 && windows }) void requiresJDK7AndWindows() { result << 'JDK 7 Windows' } }
Tasks类用于完成alwaysExecuted
,supportedOnlyInJDK6
,requiresJDK7AndWindows
这三个任务,但不一样的任务对环境和系统的要求都不同,这里使用@OnlyIf
来代表对环境和系统的需求。
@Retention(RetentionPolicy.RUNTIME) @interface OnlyIf { Class value() }
在groovy中若是须要让注解接受闭包的话,只须要像上面这样定义一个Class类型的value值。这样OnlyIf就能够接受闭包做为其值了。
接着写处理类:
class Runner { static <T> T run(Class<T> taskClass) { def tasks = taskClass.newInstance() def params = [jdk:6, windows: false] tasks.class.declaredMethods.each { m -> if (Modifier.isPublic(m.modifiers) && m.parameterTypes.length == 0) { def onlyIf = m.getAnnotation(OnlyIf) if (onlyIf) { Closure cl = onlyIf.value().newInstance(tasks,tasks) cl.delegate = params if (cl()) { m.invoke(tasks) } } else { m.invoke(tasks) } } } tasks } }
和java相似,经过反射拿到Task对象的方法,接着获取其OnlyIf注解,若是获取成功,则提取OnlyIf的闭包进行调用。
trait是groovy中独有的面向对象的语法特性,他具有以下功能:
Trait能够被看做是具备方法实现和状态的接口,使用trait
关键字定义:
trait FlyingAbility { String fly() { "I'm flying!" } }
上面就定义了一个飞行能力的特证,它的使用方法和接口同样,都是使用implements
关键字:
class Bird implements FlyingAbility {} def b = new Bird() assert b.fly() == "I'm flying!"
这个看上去感受跟继承有点相似,但又不同,trait仅仅是将其方法和状态嵌入到实现类中,而没有继承中的那种上下级的父子关系。
trait中的一些语法特性:
钻石问题
,其获取方式有所不一样,以下:trait Named { public String name } class Person implements Named {} def p = new Person() p.Named__name = 'Bob'
以上简单介绍了groovy中面向对象的相关知识,更详细的资料请参考官方文档