::
не является мутантной операцией. Это означает, что x :: xs
вернет список типа List[ commonSupertypeOf[ typeOf[x], elementTypeOf[xs] ] ]
(это не настоящий скала-код, но я надеюсь, что моя точка зрения найдется), но это не изменит тип xs
. Если xs
имеет тип List[Float]
, а x
имеет тип Integer
, то выражение x :: xs
будет иметь тип List[Numeric]
, но тип xs
по-прежнему List[Float]
, поэтому ничего не нарушается.
add
однако, является мутантной операцией. xs.add(x)
добавит Integer
к Stack
, типом которого является Stack<Float>
, что явно является ошибкой.
Это объясняет, почему выполнение x :: xs
не опасно. Теперь, чтобы объяснить, почему он печатает:
Характерная особенность ::
на List[A]
: def :: [B >: A] (x: B) : List[B]
.
Это означает, что для любых типов A
и B
, где B
является супертипом A
, ::
, если задано значение типа B
, а список типа A
будет составить список типа B
. Поэтому, когда вы делаете someInteger :: someFloats
, компилятор делает вывод, что B
равно Numeric
, а A
равно Float
и все работает.
В терминах Java это будет <B supertypeOf A> List<B> prepend(B item)
, за исключением того, что supertypeOf
не является законным Java.