型の帰属は、可能なすべての有効な型から、式から期待される型をコンパイラに伝えるだけです。
型は、分散や型宣言などの既存の制約を尊重する場合に有効であり、適用される式が " is a " である型のいずれかであるか、スコープ内で適用される変換があるかのいずれかです。
したがって、java.lang.String extends java.lang.Object
、したがって、 anyString
もObject
です。あなたの例では、式をではなくs
として扱いたいと宣言しました。それを妨げる制約はなく、目的の型は a型の 1 つであるため、機能します。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}
| ‘:’ ‘_’ ‘*’