Groovy中的面向對象

来源:http://www.cnblogs.com/futureli/archive/2017/06/14/7007867.html
-Advertisement-
Play Games

前面說到groovy支持腳本和類,前面一節已將簡單說了腳本和類之間的關係,這一節主要介紹一下groovy中類的相關知識,即面向對象相關知識。 1.類型 1.1 原始類型 groovy中支持的原始數據類型與java相同,分別是boolean,char,short,int,long,float,doub ...


前面說到groovy支持腳本和類,前面一節已將簡單說了腳本和類之間的關係,這一節主要介紹一下groovy中類的相關知識,即面向對象相關知識。

1.類型

1.1 原始類型

groovy中支持的原始數據類型與java相同,分別是boolean,char,short,int,long,float,double。

1.2 類

groovy中的類與java中很相似,但有以下幾點是groovy特有的:

  • public修飾的欄位會被自動轉換成屬性變數,這樣可以避免很多冗餘的get和set方法。
  • 如果屬性或方法沒有訪問許可權修飾符,那麼預設是public,而java中是proteced。
  • 類名不需要和文件名相同。
  • 一個文件中可以定義多個一級類。如沒有定義類,則這個groovy文件被認為是腳本文件。

1.2.1 普通類

groovy的普通類和java類似,使用new關鍵字獲得實例。

1.2.2 內部類

內部類也基本類似,下麵給一個例子:

class Outer2 {
    private String privateStr = 'some string'

    def startThread() {
       new Thread(new Inner2()).start()
    }

    class Inner2 implements Runnable {
        void run() {
            println "${privateStr}."
        }
    }
}

1.2.3 抽象類

抽象類也與java基本類似:

abstract class Abstract {         
    String name

    abstract def abstractMethod() 

    def concreteMethod() {
        println 'concrete'
    }
}

1.3 介面

groovy的介面和java也基本類似,支持介面繼承介面。

1.4 構造方法

groovy的構造方法和java就有略微不同了,groovy的構造方法支持位置參數命名參數,下麵具體看。

1.4.1 位置參數構造方法

位置構造參數跟java中的通常構造方法類似,不同位置的參數具有不同的含義。如下:

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也能從內部給你做初始化。

1.4.2 命名參數構造方法

命名參數構造方法不需要用戶定義,當一個類沒有構造方法的時候,其預設有一個命名參數構造方法。

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) 

1.5 方法

定義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" }

1.5.1 方法的命名參數

在自定義的方法中要使用命名參數的話,就要使用Map作為唯一參數,如下:

def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)

1.5.2 方法的預設參數

groovy方法支持預設參數,這樣就是的其參數變得可選,當參數沒有被填入,則會使用預設參數:

def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)

1.5.3 方法的可變長參數

這個在java中也是存在的,舉個簡單的例子:

def foo(Map args) { "${args.name}: ${args.age}" }
foo(name: 'Marie', age: 1)

1.6 註解

groovy中的註解跟java中的類似,但又比java中多了一些特性,下麵簡單介紹一下。

1.6.1 註解的閉包參數

在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的閉包進行調用。

2 Traits(特征)

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中支持定義抽象方法,其實現類必須實現此抽象方法。
  • trait中可以定義私有方法,其實現類無法訪問。
  • trait中的this關鍵字指其實現類。
  • trait可以實現介面。
  • trait中可定義屬性,此屬性會自動被附加到實現此trait的類中。
  • trait可定義私有欄位由於存儲相關狀態。
  • trait可定義公共欄位,但為了避免鑽石問題,其獲取方式有所不同,如下:
trait Named {
    public String name                      
}
class Person implements Named {}            
def p = new Person()                        
p.Named__name = 'Bob'   
  • 第一個類可以實現多個trait。
  • 實現類可重寫trait中的預設方法。
  • trait可以繼承另一個trait使用關鍵字extends,若要繼承多個則使用implements關鍵字。
  • 可以在運行時動態實現trais,使用關鍵字as。

以上簡單介紹了groovy中面向對象的相關知識,更詳細的資料請參考官方文檔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ——基於es6:Promise/A+ 規範簡單實現 非同步流程式控制制思想 前言: nodejs強大的非同步處理能力使得它在伺服器端大放異彩,基於它的應用不斷的增加,但是非同步隨之帶來的嵌套、難以理解的代碼讓nodejs看起來並沒有那麼優雅,顯得臃腫。類似於這樣的代碼: 上面的代碼 println中定義了va ...
  • 隨著Android的蓬勃發展, CPU的架構也越來越多. 早期只支持ARMv5, 截至目前, 支持的架構已達三類七種: ARM(ARMv5,ARMv7 (從2010年起),ARMv8), x86(x86 (從2011年起),x86_64 (從2014年起)) ,MIPS(MIPS (從2012年起) ...
  • 電池標稱電壓 定義如下圖, 以25度為例,20度再往上點, 4V 放一下電就往下掉, 3V 放一下電就往下掉, 假設 3.8V 是擁有最多 capacity 可以 discharge 的電壓,放電放了很久仍維持 3.8V, 因此我們定義 3.8V 為這顆電池的標稱電壓,(不同型號的電池也許不一樣) ...
  • Apple取消了oc的指針以及其他不安全的訪問的使用,捨棄的smalltalk語法,全面改為點語法,提供了類似java的命名空間 範型 重載; 首先我們瞭解一下Swift這門語言。Swift就像C語言一樣,使用變數來進行存儲並通過變數名來關聯值。在swift中廣泛的使用著不可變的變數,也就是我們常說 ...
  • Origin 一顆電池被拉載後,會產生電流及電壓如下圖, 如何計算其電池內阻呢 其公式為 R = |delta(V) / delta(I)| 公式推導如下: V1 = 10 I1R 左圖 V2 = 10 I2R 右圖 === 10 = V1 + I1R 10 = V2 + I2R === V1 + ...
  • 上一篇博文寫的是Picasso基本使用和源碼完全解析,Picasso的源碼閱讀起來還是很順暢的,然後就想到Glide框架,網上大家也都推薦使用這個框架用來載入圖片,正好我目前的寫作目標也是分析當前一些流行的框架源碼,那就也來解析下Glide的源碼吧,而且有了Picasso源碼的分析相信很快就搞定Gl... ...
  • 轉載文章地址:http://www.jianshu.com/p/27ba2759b221 ...
  • Block簡介 Block使用場景,可以在兩個界面的傳值,也可以對代碼封裝作為參數的傳遞等。用過GCD就知道Block的精妙之處。 Block是一種比較特殊的數據類型。它可以保存一段代碼,在合適的時候取出來調用。 Block的修飾 ARC情況下 1.如果用copy修飾Block,該Block就會存儲 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...