首页 文章

Scala Nothing数据类型

提问于
浏览
6

我知道Scala没有什么是底层类型 . 当我看到API时,它从“Any”扩展,这是层次结构中的顶层 .

现在,由于Scala不支持多重继承,我们怎么能说它是底层类型 . 换句话说,它不直接继承所有类或特征,如Seq,List,String,Int等 . 如果是这种情况我们怎么能说它是所有类型的底部?

我的意思是,如果我们能够将List [Nothing](Nil)分配给List [String],因为List在scala中是协变的,因为Nothing和String类型之间没有直接关联 . 我们知道什么都不是底层类型,但我很难看到String和Nothing之间的关系,就像我在上面的例子中所说的那样 .

谢谢和问候,穆罕默德

2 回答

  • 3

    现在,因为Scala不支持多重继承

    Scala确实支持使用trait mixin进行多重继承 . 这当前不是可交换的,即类型 A with BB with A 不相同(这将与Dotty一起发生),但仍然是它的优点,因为它通过其线性化规则解决了钻石问题 .

    顺便说一下, Null 是另一个底层类型,继承自Java(也可以说它有一个 Nothing 底部类型,因为你可以在任何可能的地方抛出运行时异常) .

    我认为你需要区分类继承和类型边界 . 将 Nothing 定义为底部类型没有矛盾,尽管它不会从您想要的任何类型继承,例如 List . 它更像是一种能力,即抛出异常的能力 .

    如果我们能够将List [Nothing](Nil)分配给List [String],因为List在scala中是协变的,因为Nothing和String类型之间没有直接关联

    是的,底部类型的想法是 Nothing (也是许多其他的东西)也是 String 的子类型 . 所以你可以写

    def foo: String = throw new Exception("No")
    

    这只能起作用,因为 Nothing (抛出异常的类型)比声明的返回类型 String 更具体 .

  • 3

    tl;dr summaryNothing 是每种类型的子类型,因为规范是这样说的 . 它无法从语言中解释 . 每种语言(或至少几乎每种语言)都有一些无法用语言解释的核心内容,例如: java.lang.Object 没有超类,即使每个类都有一个超类,因为即使我们不写一个 extends 子句,该类也会隐式获得一个超类 . 或者"bootstrap paradox"在Ruby中, ObjectClass 的实例,但 ClassObject 的子类,因此 Object 是其自身的间接实例(甚至更直接: ClassClass 的实例) .


    我知道Scala没有什么是底层类型 . 当我看到API时,它从“Any”扩展,这是层次结构中的顶层 . 现在,由于Scala不支持多重继承,我们怎么能说它是底层类型 .

    这有两种可能的答案 .

    简单而简短的答案是:because the spec says so . 规范说 Nothing 是所有类型的子类型,因此 Nothing 是所有类型的子类型 . 怎么样?我们不知道它是什么 . 让编译器设计者担心如何在他们的编译器中表示这个事实 . 你关心 Any 能够超级吗?您是否关心编译器内部如何表示 def

    稍微长一点的答案是:是的,这是真的, Nothing 继承自 Any ,仅来自 Any . 但!继承与子类型不同 . 在Scala中,继承和子类型紧密相连,但它们并不是一回事 . Nothing 只能从一个类继承的事实并不意味着它不能是多个类型的子类型 . 类型与类不同 .

    事实上,非常具体,规范甚至没有说 Nothing 是所有类型的子类型 . 它只说 Nothing conforms to all types .

    换句话说,它不直接继承所有类或特征,如Seq,List,String,Int等 . 如果是这种情况我们怎么能说它是所有类型的底部?

    我们可以再次说,因为规范说我们可以这么说 .

    我们怎么能说 def 定义了一个方法?因为the spec says so . 我们怎么能说 a b ca.b(c) 意思相同, a b_: c 意味着同样的事情 { val __some_unforgeable_id__ = a; c.b_:(__some_unforgeable_id__) } ?因为the spec says so . 我们怎么能说 "" 是一个字符串而 '' 是一个字符?因为the spec says so .

    我的意思是,如果我们能够将List [Nothing](Nil)分配给List [String],因为List在scala中是协变的,因为Nothing和String类型之间没有直接关联 .

    是的,类型 NothingString 之间存在直接关联 . NothingString 的子类型,因为 Nothing 是所有类型的子类型,包括 String .

    正如我们所知,没有什么是底层类型,但我很难看到String和Nothing之间的关系,就像我在上面的例子中所说的那样 .

    StringNothing 之间的关系是 NothingString 的子类型 . 为什么?因为规范说的如此 .

    编译器知道 NothingString 的子类型,就像它知道 1Int 的实例一样,并且有一个 + 方法,即使你看一下Scala标准库的源代码,the Int class is actually abstract and all its methods have no implementation .

    Someone, somewhere wrote some code within the compiler that knows how to handle adding two numbers,即使这些数字实际上表示为JVM原语,甚至不存在于Scala对象系统中 . 同样的方式,someone, somewhere wrote some code within the compiler that knows that Nothing is a subtype of all types即使在the source code of Nothing中没有表示这个事实(甚至不能代表) .

相关问题