Рассмотрим этот пример:
CommonHandler. java:
Общий обработчик с дополнительными логами c. Здесь все очень просто:
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?
. Насколько я знаю, мы не можем объявить явно типы платформ в Kotlin с синтаксисом R!
.