在Nothing上调用任何方法

时间:2018-06-26 09:20:38

标签: kotlin subtyping

尽管is not explicitly stated并不是所有类型的子类型,但它(除其他外)建议:

fun f(x:Float) { }
fun g(x:Char) { }

fun dead(q: Nothing) {
    f(q)
    g(q)
}

但是,此操作失败,并显示“未解析的引用”:

fun dead(q: Nothing) {
    q.not()
}

这是错误还是功能?

注意:

  1. 第一段代码会编译(带有警告),第二段代码不会编译
  2. 可以使用Nothing类型的接收器,例如调用toString()
  3. 这是合法的:{b:Boolean -> b.not()}(q)
  4. 也要上播:(q as Boolean).not()
  5. Equivalent question for Scala

2 个答案:

答案 0 :(得分:3)

Nothing之所以是Nothing是有原因的。您不能在其上调用任何功能。此外,not()仅适用于Boolean,因此Nothing中不存在。实际上,Nothing上没有方法:

/**
 * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example,
 * if a function has the return type of Nothing, it means that it never returns (always throws an exception).
 */
public class Nothing private constructor()

文档几乎解释了它的存在。

尽管有一个漏洞。如果您从函数返回Nothing?会怎样?

fun dead(): Nothing? {
    return null
}

是的。它只能返回null

@JvmStatic
fun main(args: Array<String>) {
    dead() // will be null
}

我不会说有一个有效的用例可以做到这一点,但是有可能。

Nothing表示树中无的示例:

sealed class Tree<out T>() {
    data class Node<out T>(val value: T,
                           val left: Tree<T> = None,
                           val right: Tree<T> = None): Tree<T>()
    object None: Tree<Nothing>()
}

Nothing表示没有子节点的叶节点。

答案 1 :(得分:2)

前提本身是没有道理的。 Nothing是无法实例化的类。您将永远不会拥有一个包含Nothing实例的变量。

这意味着以Nothing作为参数的函数永远不会被调用,因为您无法获得Nothing实例传递给它。您在其中编写的任何内容都是无关紧要的,就像首先存在的类似功能一样。

使

Nothing像所有类型的子类型一样工作,以便诸如throwreturn之类的语言功能的某些用法可以很好地与类型系统配合使用。本质上,编译器使您可以在需要其他类型的地方传递Nothing,因为它知道您永远不会真正到达该代码(因为再次,您无法获得Nothing实例),因此您传递的内容都没有关系。