¿Cuál es el propósito de las asignaciones de tipo en Scala?

No hay mucha información en la especificación sobre qué tipo de adscripción es, y ciertamente no hay nada allí sobre el propósito de la misma. Además de “hacer que varargs pasen”, ¿para qué usaría la adscripción de tipo? A continuación se muestra algunos scala REPL para la syntax y los efectos de su uso.

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 

    La adscripción de tipos simplemente le dice al comstackdor qué tipo espera de una expresión, de todos los posibles tipos válidos.

    Un tipo es válido si respeta las restricciones existentes, como la varianza y las declaraciones de tipo, y es uno de los tipos de expresión a la que se aplica ” es un “, o hay una conversión que se aplica en el ámbito.

    Entonces, java.lang.String extends java.lang.Object , por lo tanto, cualquier String es también un Object . En su ejemplo, declaró que desea que la expresión s se trate como un Object , no como una String . Como no hay restricciones que lo impidan y el tipo deseado es uno de los tipos s es a , funciona.

    Ahora, ¿por qué querrías eso? Considera esto:

     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) 

    También podría haber arreglado esto por tipo de escritura en la statement ss , o podría haber declarado que el tipo de ss es Set[AnyRef] .

    Sin embargo, las declaraciones de tipo solo logran lo mismo siempre que asigne un valor a un identificador. Lo que uno siempre puede hacer, por supuesto, si a uno no le importa tirar el código con identificadores de un solo uso. Por ejemplo, lo siguiente no comstack:

     def prefixesOf(s: String) = s.foldLeft(Nil) { case (head :: tail, char) => (head + char) :: head :: tail case (lst, char) => char.toString :: lst } 

    Pero esto hace:

     def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { case (head :: tail, char) => (head + char) :: head :: tail case (lst, char) => char.toString :: lst } 

    Sería una tontería usar un identificador aquí en lugar de Nil . Y aunque podría simplemente escribir List[String]() , eso no siempre es una opción. Considere esto, por ejemplo:

     def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None case (vowel, _) => vowel } 

    Para la referencia, esto es lo que la especificación de Scala 2.7 (borrador del 15 de marzo de 2009) tiene que decir acerca de la adscripción de tipo:

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

    Una posibilidad es cuando la red y el nivel de protocolo de serie, entonces esto:

     val x = 2 : Byte 

    es mucho más limpio que

     val x = 2.asInstanceOf[Byte] 

    La segunda forma también es una conversión en tiempo de ejecución (no manejada por el comstackdor) y podría dar lugar a algunas condiciones interesantes de exceso / defecto.

    Uso la adscripción de tipo al papel sobre agujeros en la inferencia de tipo de Scala. Por ejemplo, foldLeft sobre una colección de tipo A toma un elemento inicial de tipo B y una función (B, A) => B que se usa para doblar los elementos de la colección en el elemento inicial. El valor real de tipo B se deduce del tipo del elemento inicial. Como Nil extiende List [Nothing], usarlo como elemento inicial causa problemas:

     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) 

    Alternativamente, puede usar List.empty [Int] en lugar de Nil: List [Int].

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

    editar: List.empty [A] se implementa como

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

    (fuente)

    Esta es efectivamente una forma más detallada de Nil: Lista [A]

    Puede encontrar este hilo iluminando, si es un poco complicado para seguir. Lo importante a tener en cuenta es que está agregando sugerencias de restricciones al comprobador de tipos: le da un poco más de control sobre lo que está haciendo esa fase de comstackción.

    Inferencia de tipo: podemos omitir el nombre explícito del tipo de algo en el código fuente, llamado Inferencia de tipo (aunque se requiere en algunos casos excepcionales).

    Tipo de Asignación: Ser explícito sobre el tipo de algo se llama una Asignación de Tipo. ¿Qué diferencia puede hacer?

    ex: val x = 2: Byte

    también vea: 1. Podemos dar vuelta explícitamente tipo a nuestras funciones

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

    Otra forma de declarar esto podría ser:

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

    Aquí no dimos la Option[Option[String]] devolver el tipo explícitamente y el Comstackdor lo dedujo como Some[Option[String]] . Por qué Some[Option[String]] se debe a que usamos la adscripción de tipo en la definición.

    1. Otra forma en que podemos usar la misma definición es:

      def t3 = Some(None)

      > t3: Some[None.type]

    Esta vez No le dijimos explícitamente nada al comstackdor (ni esta defi). Y dedujo nuestra definición como Some [None.type]