这个问题在这里已经有了答案:
How do I call extension methods from outside the class they are defined in?
(3 个回答)
3年前关闭。
我正在尝试创建一个非常简单的事务管理器,如下所示:
object PersistenceManager {
private val dataSource: DataSource by lazy {
val config = ConfigFactory.load()
hikari(config.getConfig("postgres"))
}
private fun hikari(appConfig: Config): DataSource {
// init datasource
}
fun <T> transaction(statement: Connection.() -> T): T {
val connection = dataSource.connection
try {
return connection.statement()
} catch (e: Exception) {
connection.rollback()
throw e
} finally {
connection?.close()
}
}
}
class BrandsDB {
private val query = "select name from brands order by name"
fun Connection.getAll(): List<String> {
val ps = this.prepareStatement(query)
val rs = ps.executeQuery()
return JdbcMapperFactory.newInstance()
.newMapper(String::class.java)!!.stream(rs).toList()
}
}
class BrandsService(private val brandsDB: BrandsDB) {
fun getBrands(): List<String> {
return transaction {
brandsDB.getAll() // I'd like to do something like this but since
// getAll() method belongs to Connecion, I can't
}
}
}
所以这一切背后的想法是我可以在一个
transaction
中进行多个查询。如果出现任何问题,我可以回滚的 block (我应该在这些查询中插入或更新)。我还想避免将连接传递给 brandsDB.getAll()
方法,但让它以“隐式”方式获得连接。我知道我可以提取
getAll()
方法到它自己的文件或制作 BrandsDB
类一个对象,但这可以在任何地方以静态方式调用该方法,这是我不喜欢的。我也不想将任何与数据库相关的代码放在 BrandsService
中。 ,只有业务逻辑应该去那里。这可能吗?
最佳答案
Connection
是 Java 中的接口(interface)(不是类!),因此您可以创建自己的接口(interface)来扩展它并委托(delegate)给它。
interface OurConnection : Connection {
fun getAll() : SomeType
}
fun <T> PersistenceManager.extendedTransaction(action: OurConnection.() -> T) : T {
//call the original method
return PersistenceManager.transaction {
object : OurConnection, Connection by this {
override fun getAll() = TODO("implement me")
}.action()
}
}
我使用委托(delegate)实现,隐式委托(delegate)
Connection
我的界面中的方法。它是 Connection by this
行,其中 this
是来自 PersistenceManager.transaction
的 lambda 接收器对象函数调用。
关于kotlin - 来自不同类的调用扩展功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55415060/