Ответ Пелотома довольно неплохо описывает теорию, вот несколько примеров, поясняющих ситуацию:
def foo(x: Any) {
println("any")
}
def foo(x: String) {
println("string")
}
def main(args: Array[String]) {
val a: Any = new Object
val s = "string"
foo(a) // any
foo(s) // string
foo(s: Any) // any
foo(a.asInstanceOf[String]) // compiles, but ClassCastException during runtime
foo(a: String) // does not compile, type mismatch
}
Как видите, типовая надпись может использоваться для устранения неоднозначностей. Иногда они могут быть неразрешимы компилятором (см. Позже), который сообщит об ошибке, и вы должны устранить ее. В других случаях (как в примере) он просто использует «неправильный» метод, а не тот, который вы хотите. foo(a: String)
не компилируется, показывая, что тип ascription не приведен. Сравните это с предыдущей строкой, где компилятор доволен, но вы получите исключение, поэтому ошибка обнаруживается затем с типом ascription.
Вы получите неразрешимую неоднозначность, если вы также добавите метод
def foo(xs: Any*) {
println("vararg")
}
В этом случае первый и третий вызов foo не скомпилируется, так как компилятор не может решить, хотите ли вы вызывать foo с одним параметром Any или с varargs, так как оба они кажутся одинаково хорошими => Вы должны использовать атрибуцию типа, чтобы помочь компилятору.
Редактировать см. Также Какова цель начертания шрифтов в Scala?