Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在没有Java的纯Kotlin中实现接口null vs throw分派_Java_Kotlin_Interface_Kotlin Null Safety - Fatal编程技术网

如何在没有Java的纯Kotlin中实现接口null vs throw分派

如何在没有Java的纯Kotlin中实现接口null vs throw分派,java,kotlin,interface,kotlin-null-safety,Java,Kotlin,Interface,Kotlin Null Safety,考虑这个例子: CommonHandler.java: 具有附加逻辑的公共处理程序。这里非常简单: import kotlin.jvm.functions.Function0; 公共类CommonHandler{ 私有void docooltuffever(){/*做一些很酷的事情*/} 私有void docooltuffiter(){/*做一些很酷的事情*/} public R getResult(函数0提供程序){ R结果; doCoolStuffBefore(); 试一试{ 结果=pro

考虑这个例子:


CommonHandler.java

具有附加逻辑的公共处理程序。这里非常简单:

import kotlin.jvm.functions.Function0;
公共类CommonHandler{
私有void docooltuffever(){/*做一些很酷的事情*/}
私有void docooltuffiter(){/*做一些很酷的事情*/}
public R getResult(函数0提供程序){
R结果;
doCoolStuffBefore();
试一试{
结果=provider.invoke();
}最后{
doCoolStuffAfter();
}
返回结果;
}
}

NullableHandler.kt

如果操作引发异常,则返回
null
的处理程序版本。结果的类型为
R?

class NullableHandler : CommonHandler() {
  override fun <R> getResult(provider: Function0<R>): R? {
    return try {
      super.getResult(provider)
    } catch(ex: Throwable) {
      null
    }
  }
}

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显式声明平台类型语法。

我认为简单的解决方案是让CommonHandler的getResult返回可为null的结果,然后处理null返回,因为它是一个异常。至少一开始我是这么想的

因此,根据提示,我们将公共处理程序定义为

open class CommonHandler {
    private fun doCoolStuffBefore() { /* do some cool stuff */
    }

    private fun doCoolStuffAfter() { /* do some cool stuff */
    }

    open fun <R> getResult(provider: Function0<R>): R? {
        doCoolStuffBefore()
        return try {
            provider.invoke()
        } finally {
            doCoolStuffAfter()
        }
    }
}
开放类CommonHandler{
私人娱乐doCoolStuffBefore(){/*做一些很酷的事情*/
}
私人娱乐doCoolStuffAfter(){/*做一些很酷的事情*/
}
打开fun getResult(提供程序:函数0):R{
doCoolStuffBefore()
回击{
provider.invoke()
}最后{
doCoolStuffAfter()
}
}
}
NullableHandler不会更改,但会更改ThrowingHandler

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) ?: throw AnotherWrappedException("whooops")
        } catch(ex: Throwable) {
            throw WrappedException("Throwing handler failed with exception: ${ex.javaClass.name}", ex)
        }
    }

}
class ThrowingHandler:CommonHandler(){
类WrappedException(消息:字符串,原因:可丢弃?):异常(消息,原因)
重写fun getResult(提供程序:函数0):R{
回击{
super.getResult(提供者)?:抛出另一个WrappedException(“Whoops”)
}捕获(例如:可丢弃){
抛出WrappedException(“抛出处理程序失败,异常:${ex.javaClass.name}”,ex)
}
}
}
如果值不为null,则使用elvis运算符返回值;如果值为null,则抛出另一个WrappedException(“Whoops”)


你觉得怎么样?它能为您工作吗?

我认为简单的解决方案是让CommonHandler的getResult返回可为null的结果,然后处理null返回,因为它是一个异常。至少一开始我是这么想的

因此,根据提示,我们将公共处理程序定义为

open class CommonHandler {
    private fun doCoolStuffBefore() { /* do some cool stuff */
    }

    private fun doCoolStuffAfter() { /* do some cool stuff */
    }

    open fun <R> getResult(provider: Function0<R>): R? {
        doCoolStuffBefore()
        return try {
            provider.invoke()
        } finally {
            doCoolStuffAfter()
        }
    }
}
开放类CommonHandler{
私人娱乐doCoolStuffBefore(){/*做一些很酷的事情*/
}
私人娱乐doCoolStuffAfter(){/*做一些很酷的事情*/
}
打开fun getResult(提供程序:函数0):R{
doCoolStuffBefore()
回击{
provider.invoke()
}最后{
doCoolStuffAfter()
}
}
}
NullableHandler不会更改,但会更改ThrowingHandler

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) ?: throw AnotherWrappedException("whooops")
        } catch(ex: Throwable) {
            throw WrappedException("Throwing handler failed with exception: ${ex.javaClass.name}", ex)
        }
    }

}
class ThrowingHandler:CommonHandler(){
类WrappedException(消息:字符串,原因:可丢弃?):异常(消息,原因)
重写fun getResult(提供程序:函数0):R{
回击{
super.getResult(提供者)?:抛出另一个WrappedException(“Whoops”)
}捕获(例如:可丢弃){
抛出WrappedException(“抛出处理程序失败,异常:${ex.javaClass.name}”,ex)
}
}
}
如果值不为null,则使用elvis运算符返回值;如果值为null,则抛出另一个WrappedException(“Whoops”)


你觉得怎么样?它是否适用于您?

如果您将返回类型定义为可为null的R:

开放类CommonHandler{
私人娱乐doCoolStuffBefore(){/*做一些很酷的事情*/
}
私人娱乐doCoolStuffAfter(){/*做一些很酷的事情*/
}
打开有趣的getResult(提供程序:()->R):R{
doCoolStuffBefore()
回击{
provider.invoke()
}最后{
doCoolStuffAfter()
}
}
}
然后可以将作用域缩小到子类中不可为null的R

class ThrowingHandler:CommonHandler(){
类WrappedException(消息:字符串,原因:可丢弃?):异常(消息,原因)
覆盖有趣的getResult(提供程序:()->R):R{
回击{
super.getResult(提供者)!!
}捕获(例如:可丢弃){
抛出WrappedException(“抛出处理程序失败,异常:${ex.javaClass.name}”,ex)
}
}
}

您的ThrowableMhandler假设API无法返回null,因此使用
运算符,并让任何KotlinNPE包装在WrappedException中。这实际上比您已经拥有的要好,因为意外异常包含在包装器中,而不是冒泡到代码中其他地方的JavaNPE。如果您需要包装一个应该能够返回null的API,那么我认为您还需要一个NullableThrowingHandler。

如果您将返回类型定义为nullable R:

开放类CommonHandler{
私人娱乐doCoolStuffBefore(){/*做一些很酷的事情*/
}
私人娱乐doCoolStuffAfter(){/*做一些很酷的事情*/
}
打开有趣的getResult(提供程序:()->R):R{
doCoolStuffBefore()
回击{
provider.invoke()
}最后{
doCoolStuffAfter()
}
}
}