Scala中类型归属的目的是什么?

dav*_*000 71 scala static-typing ascription

关于什么类型的归属,规范中没有太多信息,并且当然没有关于它的目的的任何信息.除了"使传递varargs工作",我会使用什么类型的归属?下面是一些scala REPL的语法和使用它的效果.

scala> val s = "Dave"
s: java.lang.String = Dave

scala> val p = s:Object
p: java.lang.Object = Dave

scala> p.length
<console>:7: error: value length is not a member of java.lang.Object
       p.length
         ^
scala> p.getClass
res10: java.lang.Class[_ <: java.lang.Object] = class java.lang.String

scala> s.getClass
res11: java.lang.Class[_ <: java.lang.Object] = class java.lang.String

scala> p.asInstanceOf[String].length
res9: Int = 4
Run Code Online (Sandbox Code Playgroud)

Dan*_*ral 75

类型归属只是从所有可能的有效类型告诉编译器您期望表达式的类型.

如果类型遵循现有约束(例如方差和类型声明),则它是有效的,并且它是应用于" is a " 的表达式之一,或者是在范围内应用的转换.

所以,java.lang.String extends java.lang.Object因此任何String也是一个Object.在您的示例中,您声明要将表达式s视为a Object,而不是a String.由于没有任何约束阻止它,并且所需类型是其中一种类型s 是a,它起作用.

现在,你为什么要这样?考虑一下:

scala> val s = "Dave"
s: java.lang.String = Dave

scala> val p = s: Object
p: java.lang.Object = Dave

scala> val ss = scala.collection.mutable.Set(s)
ss: scala.collection.mutable.Set[java.lang.String] = Set(Dave)

scala> val ps = scala.collection.mutable.Set(p)
ps: scala.collection.mutable.Set[java.lang.Object] = Set(Dave)

scala> ss += Nil
<console>:7: error: type mismatch;
 found   : scala.collection.immutable.Nil.type (with underlying type object Nil)
 required: java.lang.String
       ss += Nil
             ^

scala> ps += Nil
res3: ps.type = Set(List(), Dave)
Run Code Online (Sandbox Code Playgroud)

你也可以按类型ascripting这个固定sss声明中,或者你也可以声明ss的类型是Set[AnyRef].

但是,只要您为标识符赋值,类型声明就会实现相同的功能.当然,如果一个人不关心用一次性标识符乱丢代码,那么总是可以做到.例如,以下内容无法编译:

def prefixesOf(s: String) = s.foldLeft(Nil) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}
Run Code Online (Sandbox Code Playgroud)

但这样做:

def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}
Run Code Online (Sandbox Code Playgroud)

在这里使用标识符代替,这将是愚蠢的Nil.虽然我可以改写List[String](),但这并不总是一种选择.考虑一下,例如:

def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { 
  case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
  case (vowel, _) => vowel
}
Run Code Online (Sandbox Code Playgroud)

作为参考,这是Scala 2.7规范(2009年3月15日草案)关于类型归属的说法:

Expr1 ::= ...
        | PostfixExpr Ascription

Ascription ::= ‘:’ InfixType
             | ‘:’ Annotation {Annotation}
             | ‘:’ ‘_’ ‘*’
Run Code Online (Sandbox Code Playgroud)


Kev*_*ght 27

一种可能性是网络和串行协议级别的东西,然后这个:

val x = 2 : Byte
Run Code Online (Sandbox Code Playgroud)

远远比清洁

val x = 2.asInstanceOf[Byte]
Run Code Online (Sandbox Code Playgroud)

第二种形式也是运行时转换(不由编译器处理),可能会导致一些有趣的上/下溢条件.

  • 为什么不使用日常语法?`val x:Byte = 2` (17认同)