Тип ascription просто сообщает компилятору, какой тип вы ожидаете от выражения, от всех возможных допустимых типов.
Тип действителен, если он учитывает существующие ограничения, такие как объявления отклонений и типов, и это либо один из типов, к которым применяется выражение, которое « представляет собой », либо существует преобразование, которое применяется в объеме.
Итак, 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 (черновик 15 марта 2009 г.) должна сказать о типе ascription:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’