我是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中有效,所有内容都被转储到实例的 dict 中。
如果您可以告诉我如何覆盖属性设置运算符以便设置参数将自动设置dirty = true,那么
奖励积分。
感谢您的帮助。
答案 0 :(得分: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()