2013-12-18 83 views
1

我是Groovy的新手,試圖從Python跳轉。不幸的是,我根本不瞭解Java。我正在研究一個將使用MongoDB作爲後端的程序,並編寫了一個抽象的Domain類來處理訪問數據庫的細節。文檔內容是從實例的屬性動態生成的。抽象父類需要子類的類變量

import Database.Server 

abstract class Domain { 

    ObjectId _id 
    String comment 
    Date created 
    Date updated 
    Boolean dirty=false 

    static findOne(Map query=[:]) { 
     newInstance(collection().findOne(query as BasicDBObject)) 
    } 

    static find(Map query=[:]) { 
     def cursor = collection().find(query as BasicDBObject) 
     cursor.collect { doc -> newInstance(doc) } 
    } 

    static collection() { 
     //todo catch error if db hasn't been selected yet. 
     def db = Server.getDB() 
     return db.getCollection(this.collectionName) 
    } 

    static count() { 
     return collection().getCount() 
    } 

    def fields() { 
     // get all properties of the object and remove the ones we don't want to have in the collection 
     Map fieldMap = properties 
     ['class', 'collectionName', 'dirty'].each { fieldMap.remove(it) } 
     return fieldMap 
    } 

    void insert() { 
     //todo incorporate audit trail 
     this.created = new Date() 
     this.updated = new Date() 
     collection().insert(fields() as BasicDBObject) 
     this.dirty = false 
    } 

    void save() { 
     // todo incorporate audit trail 
     this.updated = new Date() 
     collection().save(fields() as BasicDBObject) 
     this.dirty = false 
    } 

    String toString() { 
     return "${collectionName}: " + fields().collect { "\n\t$it" } 
    } 
} 

所以,我想我可以通過繼承抽象類,像定義名稱的集合,從而生成一個簡單的集合:

class Test extends Domain { 
    static String collectionName = 'test' 
} 

,但是,這並不工作。 Domain中定義的方法無法看到Test中定義的collectionName變量。我怎樣才能讓Domain.collection()使用在子類中定義的變量?這工作在Python中,一切都被轉儲到實例的字典

如果您可以告訴我如何覆蓋屬性設置運算符以便設置參數將自動設置dirty = true,則可獲得獎勵積分。

感謝您的幫助。

回答

1

Groovy和Java沒有任何靜態類成員的繼承。當您在名爲Domain的常規類中說this.collectionName時,即使您通過像Test.collection()這樣的子類調用該方法,也是引用Domain.collectionName

即便如此,您也可以通過一些元編程魔法實現類似的效果。您可以在運行時添加靜態方法,通過正確的類來解析靜態屬性。不幸的是,它並不像Python的等價物那麼簡單。這裏有一個小例子:

class DomainHelper { 
    static collection(collectionName) { 
     def db = Server.getDB() 
     return db.getCollection(collectionName) 
    } 
    static apply(domainClass) { 
     domainClass.metaClass.'static'.collection = this.&collection.curry(domainClass.collectionName) 
    } 
} 
class Test { 
    static collectionName = "test" 
} 
DomainHelper.apply(Test) 
Test.collection() 
+0

感謝您的建議。無論如何要使用類別或@ Category/@ Mixin對來完成此操作嗎? 另外,我會在哪裏放'DomainHelper.apply(Test)'?如果我把它放在定義了新域的文件中,它不會被封裝在一個腳本類中,而是不會被實際執行嗎? – user3116827

+0

我最初的想法是使用mixin,但我無法從mixin類中找到訪問目標類的類的方法。可以在Test中的靜態初始化塊中調用apply方法(例如'class Test {static {DomainHelper.apply(this)} ...}')。 – ataylor