Атрибуція типу просто повідомляє компілятору, який тип ви очікуєте від виразу з усіх можливих допустимих типів.
Тип є дійсним, якщо він поважає існуючі обмеження, такі як оголошення про дисперсію та тип, і це або один із типів, до якого він застосовує вираз " є ", або існує перетворення, яке застосовується за обсягом.
Отже, java.lang.String extends java.lang.Object
отже, будь- String
який також є Object
. У своєму прикладі ви заявили, що хочете, щоб вираз s
трактувався як а Object
, а не як 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)
Ви також можете виправити це за типом, який приписується 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 р.) Про атрибуцію типу:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’