关于什么类型的归属,规范中没有太多信息,并且当然没有关于它的目的的任何信息。除了“使传递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
答案 0 :(得分:73)
类型归属只是告诉编译器您对表达式的期望类型,来自所有可能的有效类型。
如果类型尊重现有约束(例如方差和类型声明),则它是有效的,并且它是应用于“是”的表达式之一,或者存在转换适用范围。
因此,java.lang.String extends java.lang.Object
,因此任何String
也是Object
。在您的示例中,您声明要将表达式s
视为Object
,而不是String
。由于没有任何约束阻止,并且所需类型是s
类型之一,它可以正常工作。
现在,你为什么要这样?考虑一下:
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)
您也可以通过s
声明中的ss
类型来修复此问题,或者您可以将ss
的类型声明为Set[AnyRef]
。
但是,只要您为标识符赋值,类型声明就会实现相同的功能。当然,如果一个人不关心用一次性标识符乱丢代码,那么总是可以做到。例如,以下内容无法编译:
def prefixesOf(s: String) = s.foldLeft(Nil) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
但这样做:
def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
在此处使用标识符代替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
}
作为参考,这是Scala 2.7规范(2009年3月15日草案)关于类型归属的说法:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’
答案 1 :(得分:27)
一种可能性是网络和串行协议级别的东西,然后这个:
val x = 2 : Byte
比
更清洁val x = 2.asInstanceOf[Byte]
第二种形式也是运行时转换(不由编译器处理),可能会导致一些有趣的上/下溢条件。
答案 2 :(得分:0)
如果有点令人费解,你可能会发现this thread很有启发性。需要注意的重要一点是,您要向类型检查器添加约束提示 - 它可以让您更好地控制编译阶段正在执行的操作。
答案 3 :(得分:0)
我使用类型归属来描述Scala类型推断中的漏洞。例如,对类型A的集合的foldLeft采用类型B的初始元素和函数(B,A)=&gt; B,用于将集合的元素折叠到初始元素中。类型B的实际值是从初始元素的类型推断出来的。由于Nil扩展了List [Nothing],因此将其用作初始元素会导致问题:
scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)
scala> x.foldLeft(Nil)( (acc,elem) => elem::acc)
<console>:9: error: type mismatch;
found : List[Int]
required: scala.collection.immutable.Nil.type
x.foldLeft(Nil)( (acc,elem) => elem::acc)
^
scala> x.foldLeft(Nil:List[Int])( (acc,elem) => elem::acc )
res2: List[Int] = List(4, 3, 2, 1)
或者,您可以使用List.empty [Int]而不是Nil:List [Int]。
scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)
编辑:List.empty [A]实现为
override def empty[A]: List[A] = Nil
这实际上是一个更详细的Nil形式:List [A]
答案 4 :(得分:0)
类型推断:我们可以跳过在源代码中明确给出类型名称的名称,称为类型推断。(虽然在某些特殊情况下需要。)
类型归属:明确某事物的类型称为类型归属。 它可以带来什么不同?
ex:val x = 2:字节
另见: 1.我们可以明确地给我们的函数提供返回类型
def t1 : Option[Option[String]] = Some(None)
> t1: Option[Option[String]]
宣布这一点的另一种方式可能是:
def t2 = Some(None: Option[String])
> t2: Some[Option[String]]
这里我们没有明确地给出Option[Option[String]]
返回类型,而编译器将其推断为Some[Option[String]]
。
为什么Some[Option[String]]
是因为我们在定义中使用了类型归属。
我们可以使用相同定义的另一种方法是:
def t3 = Some(None)
> t3: Some[None.type]
这一次我们没有明确地告诉编译器任何东西(这个defi都没有)。并且它将我们的定义推断为某些[None.type]