Scala 什么时候不是合法的接收人?

Scala 什么时候不是合法的接收人?,scala,inheritance,types,subtyping,bottom-type,Scala,Inheritance,Types,Subtyping,Bottom Type,作为允许将假定的Nothing类型化值传递给任何函数。然而,尽管这样一个值可以作为toString()的接收器,但它不能作为一元数组的接收器(除其他外) 这是一个bug还是一个特性 注: 这是一个的Scala版本 上传作品:!(q.asInstanceOf[Boolean]) Nothing是所有其他类型(包括scala.Null)的子类型;不存在此类型的实例 换句话说,没有类型为Nothing的值。因此,与您问题中的陈述相反,您不能将Nothing类型化值传递给任何函数(即使是假设的),因为根

作为允许将假定的
Nothing
类型化值传递给任何函数。然而,尽管这样一个值可以作为
toString()
的接收器,但它不能作为
一元数组的接收器(除其他外)

这是一个bug还是一个特性

注:

  • 这是一个的Scala版本
  • 上传作品:
    !(q.asInstanceOf[Boolean])
  • Nothing是所有其他类型(包括scala.Null)的子类型;不存在此类型的实例

    换句话说,没有类型为
    Nothing
    的值。因此,与您问题中的陈述相反,您不能将
    Nothing
    类型化值传递给任何函数(即使是假设的),因为根据定义,它不存在。它也不能成为任何方法的接收者,因为它同样不存在

    因此,如果有一个bug的话,那就是编译器没有警告您已经创建了一个永远无法调用的函数



    在这种情况下,
    println(q)
    工作是因为
    Nothing
    Any
    的子类型,而
    q.toString
    工作是因为
    AnyRef
    隐式转换为
    对象,该对象支持
    toString
    。内联函数将
    q
    转换为
    Boolean
    ,这也可以,但是
    Object
    不支持
    一元数所以
    !q
    无法编译。

    您不需要向上转换。您只需指定某个类型,该类型有一个方法
    一元数\

    def dead(q: Nothing): Unit = {
      !(q: Boolean)
    }
    
    如果没有显式的类型归属,那么方法
    unary\ux
    根本无法解析,因为即使
    Nothing
    Boolean
    的子类型,它也不是
    Boolean
    的子类,因此编译器无法找到方法
    一元

    事实上,您可以定义这样的方法和函数也不是一个bug。以下是一个完全有效的程序,它使用输入类型为
    Nothing
    的函数来生成完全有意义的结果
    0
    ,而不会引发任何错误或类似错误:

    def foo[X](xs: List[X], f: (Int, X) => Int) = {
      xs.foldLeft(0)(f)
    }
    
    foo(Nil, (i: Int, n: Nothing) => 42)
    

    在类型系统中存在
    Nothing
    ,这是一个非常好的主意,因为它是一个初始对象(对于每个类型
    a
    ,只有一个函数
    Nothing=>a
    ),它简化了很多事情,因为它不会强迫您处理所有奇怪的角落情况。

    好,那么为什么q的前三个用法是合法的,而第四个用法是不合法的呢?我想这是因为Java
    Object
    和Scala
    Any
    之间存在着不稳定的关系,编译器在这两种关系中做了一些修改以使事情正常工作。具体来说,我怀疑有一个隐式的from
    Any
    to
    Object
    ,因此
    toString
    可以工作,但是
    没有。通常,子类型!=继承,即使大多数OOP主流语言倾向于将其混淆,因此这两个概念看起来几乎是同义的。假设您可以调用任何可能在类型为
    Nothing
    的变量上定义的方法,允许这样的程序有什么好处?同意子类型!=遗产但是,子类型表示
    Bool
    类型的术语可以替换为
    Nothing
    类型的术语。为什么这在表达式
    中不可能!q
    ?@cuihtlauac在“布尔型术语”中有两部分:布尔型术语和布尔型术语。您可以将术语替换为
    q
    ,但仍然必须在某个地方指定类型Bool。如果您的
    q
    类型为
    Nothing
    ,则编译器不可能推断您引用的是方法
    Bool::unary当您编写
    时!q
    。它的子类型关系决定了你可以用什么来代替什么。继承关系决定了在哪些类中查找方法。
    def foo[X](xs: List[X], f: (Int, X) => Int) = {
      xs.foldLeft(0)(f)
    }
    
    foo(Nil, (i: Int, n: Nothing) => 42)