有一个抽象类
abstract class Select<in T, out R>(val db: Db) {
abstract val sql: String
abstract fun prepare(stmt: PreparedStatement, data: T)
abstract fun parseResult(result: ResultSet): R
fun get(data: T): R {
val stmt = db.connection().prepareStatement(sql)
prepare(stmt, data)
stmt.execute()
return parseResult(stmt.resultSet)
}
}
他有继承人
object SelectUsers : Select<Unit, HashMap<Int, User>>(DbImpl) {
override val sql = "SELECT usr_id, usr_name FROM users"
override fun prepare(stmt: PreparedStatement, data: Unit) {
return
}
override fun parseResult(result: ResultSet): HashMap<Int, User> {
//не важно
}
}
嗯,挑战
users.putAll(SelectUsers.get(Unit))
实际上,我想get为data: T. 例如这样的事情:
fun get(data: T = Unit): R //на что ругается, что логично
可能吗?如果是这样,怎么办?
因此,我决定不发疯,将经典技术与中间抽象类一起使用。同时,他
prepare在那里发布了一个定义。重要的一点——这个默认值来自哪里?
你可以尝试强制
Select它提供,然后你可以用这样一对函数来表达它:@UnsafeVariance这里是必要的,因为它在( )上是Select逆变的,并且不能在返回类型中以类型安全的方式使用。但是这个函数并不突出,它唯一的用途是类型安全的,因为这两个函数都在同一个对象上调用,这意味着对于返回值的实际类型将始终是预期的子类型。Tin TTdefaultTgetgetdefaultT()T因此,
SelectUsers您将不得不重新定义函数:UPD:这个选项更好:如果你不想
defaultT()在每个子类型中实现Select,那么你可以制作一个单独的接口:并
get()使用默认值,将其作为扩展名发出:然后实现
Select也将能够实现ProvidesDefault<T>,之后就可以在get()没有参数的情况下调用它们。同时不存在方差问题。