前面說到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也基本相似,支持接口繼承接口。spa
groovy的構造方法和java就有略微不一樣了,groovy的構造方法支持位置參數
和命名參數
,下面具體看。操作系統
位置構造參數跟java中的一般構造方法相似,不一樣位置的參數具備不一樣的含義。以下:code
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也能從內部給你作初始化。htm
命名參數構造方法不須要用戶定義,當一個類沒有構造方法的時候,其默認有一個命名參數構造方法。
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中面向對象的相關知識,更詳細的資料請參考官方文檔