访问包装函数中的实例

Getting access to an instance in a wrapper function

在 Kotlin 中,我有这个函数来包装交易:

fun wrapInTransaction(code: () -> Unit) {
        realmInstance.beginTransaction();
        code.invoke()
        realmInstance.commitTransaction();
}

如何在调用的代码中访问 realmInstance

这里的简单解决方案是将 code 设为 function with receiver:

fun wrapInTransaction(code: Realm.() -> Unit) {
    realmInstance.beginTransaction();
    realmInstance.code()
    realmInstance.commitTransaction();
}

在作为 code 传递的 lambda 中,您将能够使用 this 来引用 RealmInstance 并直接使用其成员,就像在成员函数中一样。

调用 realmInstance.code() 只是调用 code 并将 realmInstance 作为接收者传递给它。

更改 wrapInTransaction 函数以接受 realmInstance 上的扩展方法,如下所示:

fun wrapInTransaction(code:Realm.() -> Unit){
    realmInstance.beginTransaction();
    realmInstance.code()
    realmInstance.commitTransaction();
}

然后你可以像这样使用它:

wrapInTransaction {
    println("realm instance is $this, instanceId: $instanceId")
}

为了示例,Realm 看起来像:

class Realm {
    val instanceId = 42
    fun beginTransaction() {
    }

    fun commitTransaction() {
    }
}

由于 Kotlin 的 Function Literals with Receiver 使得可以在 lambda 函数体内 设置 this 实例(接收器),上述技术成为可能。它使构建类型安全的构建器变得容易,这些构建器可以从 Groovy 或 Ruby.

中重新组装。

提供了有关该技术的更多示例。

其他答案正确地演示了如何将 RealmInstance 对象传递给 lambda。另外,你可以把整个函数做成一个扩展函数,让调用的地方更漂亮一点:

fun Realm.wrapInTransaction(code: Realm.() -> Unit) {
    //this is implicit
    beginTransaction();
    code()
    commitTransaction();
}

呼叫站点将如下所示:

Realm.getInstance(this).wrapInTransaction {
    createObject(User.class)
}