2013-12-18 3 views
1

Я новичок в Groovy и пытаюсь сделать прыжок с Python. К сожалению, я вообще не знаю Java. Я работаю над программой, которая будет использовать MongoDB для бэкэнд, и написала абстрактный класс домена для обработки деталей доступа к базе данных. Содержимое документа генерируется динамически из свойств экземпляра.Абстрактному родительскому классу нужна переменная класса дочернего класса

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' 
} 

, но это не работает , Методы, определенные в домене, не могут видеть переменную collectionName, определенную в Test. Как я могу заставить Domain.collection() использовать переменную, определенную в подклассе? Это работало на Python, все сбрасывается в файл dict.

Бонусные баллы, если вы можете сказать мне, как переопределить оператор установки свойств, чтобы параметр автоматически установил dirty = true.

Благодарим за помощь.

ответ

1

Groovy и Java не имеют никакого наследования статических членов класса. Когда вы говорите this.collectionName в классе groovy под названием Domain, вы ссылаетесь на Domain.collectionName, даже если вы вызываете метод через подкласс вроде Test.collection().

Несмотря на это, вы можете добиться аналогичного эффекта с небольшим количеством метапрограммной магии. Вы можете добавлять статические методы во время выполнения, разрешая статические свойства через правильный класс. К сожалению, это не так просто, как эквивалент 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. Метод apply можно вызвать в статическом блоке инициализации в тесте (например, 'class Test {static {DomainHelper.apply (this)} ...}'). – ataylor

Смежные вопросы