Какова цель присвоения типов в Scala?

В спецификации не так много информации о том, какой тип подписки есть, и там, конечно, нет ничего о цели для нее. За исключением того, что «выполнение прохождения varargs работает», что бы я использовал для ввода типа? Ниже приведен пример scala REPL для синтаксиса и эффектов его использования.

scala> val s = "Dave" s: java.lang.String = Dave scala> val p = s:Object p: java.lang.Object = Dave scala> p.length :7: error: value length is not a member of java.lang.Object p.length ^ scala> p.getClass res10: java.lang.Class[_  s.getClass res11: java.lang.Class[_  p.asInstanceOf[String].length res9: Int = 4 

    Тип ascription просто сообщает компилятору, какой тип вы ожидаете от выражения, из всех возможных допустимых типов.

    Тип действителен, если он соблюдает существующие ограничения, такие как объявления о различиях и типах, и это либо один из типов, к которому применяется выражение « is a », либо есть преобразование, которое применяется в области видимости.

    Итак, 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 :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) 

    Вы также могли бы зафиксировать это по типу ascripting 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 spec (марш 15, проект 2009 года) должен сказать о типе присвоения:

     Expr1 ::= ... | PostfixExpr Ascription Ascription ::= ':' InfixType | ':' Annotation {Annotation} | ':' '_' '*' 

    Одна из возможностей заключается в том, что сетевой и последовательный уровень протокола, а именно:

     val x = 2 : Byte 

    намного чище, чем

     val x = 2.asInstanceOf[Byte] 

    Вторая форма также представляет собой преобразование во время выполнения (не обрабатывается компилятором) и может привести к некоторым интересным условиям over / underflow.

    Я использую указание типа для бумаги над отверстиями в выводах типа Scala. Например, foldLeft над коллекцией типа A берет начальный элемент типа B и функцию (B, A) => B, которая используется для сбрасывания элементов коллекции в исходный элемент. Фактическое значение типа B выводится из типа исходного элемента. Поскольку Nil расширяет List [Nothing], использование его в качестве исходного элемента вызывает проблемы:

     scala> val x = List(1,2,3,4) x: List[Int] = List(1, 2, 3, 4) scala> x.foldLeft(Nil)( (acc,elem) => elem::acc) :9: error: type mismatch; found : List[Int] required: scala.collection.immutable.Nil.type x.foldLeft(Nil)( (acc,elem) => elem::acc) ^ scala> x.foldLeft(Nil:List[Int])( (acc,elem) => elem::acc ) res2: List[Int] = List(4, 3, 2, 1) 

    Кроме того, вы можете просто использовать List.empty [Int] вместо Nil: List [Int].

     scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc ) res3: List[Int] = List(4, 3, 2, 1) 

    edit: List.empty [A] реализовано как

     override def empty[A]: List[A] = Nil 

    (источник)

    Это фактически более подробная форма Nil: List [A]

    Вы можете найти эту нить, освещенную, если немного запутанно следовать. Важно отметить, что вы добавляете ограничения ограничений для проверки типов – это дает вам немного больше контроля над тем, что делает эта фаза компиляции.

    Вывод типа: мы можем пропустить Явное указание имени типа чего-то в исходном коде, называемое Type Inference (хотя и требуется в некоторых исключительных случаях.)

    Тип Ascription: Явное описание типа что-то называется Type Ascription. Какая разница?

    ex: val x = 2: байт

    см. также: 1. Мы можем явно указать тип возврата на наши функции

     def t1 : Option[Option[String]] = Some(None) > t1: Option[Option[String]] 

    Другим способом объявления этого может быть:

     def t2 = Some(None: Option[String]) > t2: Some[Option[String]] 

    Здесь мы явно не Option[Option[String]] тип Option[Option[String]] а Compiler вывел его как Some[Option[String]] . Почему Some[Option[String]] – это потому, что в определении мы использовали тип записи.

    1. Другим способом мы можем использовать одно и то же определение:

      def t3 = Some(None)

      > t3: Some[None.type]

    На этот раз мы явно не сказали компилятору ничего (ни это defi). И Он определил наше определение как Some [None.type]

    Давайте будем гением компьютера.