考虑这个例子:
CommonHandler.java:
具有附加逻辑的通用处理程序。这里非常简化:
import kotlin.jvm.functions.Function0;
public class CommonHandler {
private void doCoolStuffBefore() { /* do some cool stuff */ }
private void doCoolStuffAfter() { /* do some cool stuff */ }
public <R> R getResult(Function0<R> provider) {
R result;
doCoolStuffBefore();
try {
result = provider.invoke();
} finally {
doCoolStuffAfter();
}
return result;
}
}
NullableHandler.kt:
null
如果操作抛出异常,则返回的处理程序版本。结果是类型R?
class NullableHandler : CommonHandler() {
override fun <R> getResult(provider: Function0<R>): R? {
return try {
super.getResult(provider)
} catch(ex: Throwable) {
null
}
}
}
ThrowingHandler.kt:
将错误包装在其内部异常类型中的处理程序版本。结果类型为R
.
class ThrowingHandler : CommonHandler() {
class WrappedException(message: String, cause: Throwable?): Exception(message, cause)
override fun <R> getResult(provider: Function0<R>): R {
return try {
super.getResult(provider)
} catch(ex: Throwable) {
throw WrappedException("Throwing handler failed with exception: ${ex.javaClass.name}", ex)
}
}
}
api.kt:
基本上任何我们不拥有且无法修改的 API。
object Api {
fun find(query: String): Int =
if (query.length > 3) 42
else throw NoSuchElementException("Not found for $query")
fun select(query: String): String =
if (query.count { it == 'x' } > 2) "Selected"
else throw NoSuchElementException("Not found for $query")
}
现在,有了以上所有类,我们就可以实现 API 包装器了:
object ApiProxy {
private val throwingHandler = ThrowingHandler()
private val nullableHandler = NullableHandler()
fun find(query: String): Int = throwingHandler.getResult { Api.find(query) }
fun findOrNull(query: String): Int? = nullableHandler.getResult { Api.find(query) }
fun select(query: String): String = throwingHandler.getResult { Api.select(query) }
fun selectOrNull(query: String): String? = nullableHandler.getResult { Api.select(query) }
}
我的问题是,我怎样才能在不回退到 Java的情况下实现类似的层次结构,这样就有一个类/接口与可以返回R
类型或R?
类型的方法。据我所知,我们不能用R!
语法在 Kotlin 中显式声明平台类型。