¿Cuál es el propósito de las adscripciones tipo en Scala?
-
21-09-2019 - |
Pregunta
No hay mucha información en la especificación de qué tipo es adscripción, y ciertamente no hay nada allí sobre el propósito para ello. Aparte de "hacer pasar el trabajo varargs", lo que iba a utilizar el tipo de adscripción? A continuación se ofrece REPL Scala para la sintaxis 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
<console>:7: error: value length is not a member of java.lang.Object
p.length
^
scala> p.getClass
res10: java.lang.Class[_ <: java.lang.Object] = class java.lang.String
scala> s.getClass
res11: java.lang.Class[_ <: java.lang.Object] = class java.lang.String
scala> p.asInstanceOf[String].length
res9: Int = 4
Solución
Tipo de adscripción es simplemente indica al compilador qué tipo usted espera de una expresión, de todos los posibles tipos válidos.
Un tipo es válido si respeta las limitaciones existentes, tales como la varianza y declaraciones de tipo, y es uno cualquiera de los tipos de la expresión se refiere a: " es un ", o hay una conversión que se aplica en su alcance.
Así, java.lang.String extends java.lang.Object
, por lo tanto cualquier String
es también un Object
. En su ejemplo usted declaró que desea que el s
expresión a ser tratado como un Object
, no un String
. Puesto que no hay limitaciones que impiden que el tipo deseado y es uno de los tipos s
es un , funciona.
Ahora, ¿por qué quieres eso? Considere lo siguiente:
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)
También podría haber solucionado este tipo por s
ascripting en la declaración ss
, o que podría haber declarado tipo de ss
ser Set[AnyRef]
.
Sin embargo, declaraciones de tipo lograr lo mismo sólo el tiempo que va a asignar un valor a un identificador. Los cuales siempre se puede hacer, por supuesto, si uno no se preocupan por ensuciar el código con los identificadores de un solo disparo. Por ejemplo, lo siguiente no se compila:
def prefixesOf(s: String) = s.foldLeft(Nil) {
case (head :: tail, char) => (head + char) :: head :: tail
case (lst, char) => char.toString :: lst
}
Sin embargo, 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 tonto para usar un identificador de aquí en lugar de Nil
. Y a pesar de que sólo podía escribir List[String]()
lugar, eso no es siempre 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 Scala 2.7 spec (Marzo 15, 2009 PROYECTO) tiene que decir sobre el tipo de adscripción:
Expr1 ::= ...
| PostfixExpr Ascription
Ascription ::= ‘:’ InfixType
| ‘:’ Annotation {Annotation}
| ‘:’ ‘_’ ‘*’
Otros consejos
Una posibilidad es cuando la red y cosas por nivel de protocolo en serie, entonces esto:
val x = 2 : Byte
es mucho más limpio que
val x = 2.asInstanceOf[Byte]
La segunda forma es también una conversión de tiempo de ejecución (no se maneja por el compilador) y podría conducir a algunas condiciones interesantes más / subdesbordamiento.
Yo uso Tipo de adscripción de tapar agujeros en la inferencia de tipos 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 utiliza para doblar los elementos de la colección en el elemento inicial. El valor real de tipo B se infiere a partir del tipo del elemento inicial. Desde Cero extiende Lista [Nada], utilizando como elemento inicial provoca 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)
<console>: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)
Como alternativa, es posible que utilices List.empty [Int] en lugar de Cero:. Lista [Int]
scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)
edit: List.empty [A] se implementa como
override def empty[A]: List[A] = Nil
Esto es efectivamente una forma más detallado de Cero: Lista [A]
Usted puede encontrar este hilo iluminando, si un poco complicado de seguir. Lo importante a destacar es que va a añadir a la restricción insinúa comprobador de tipos -. Le da un poco más de control sobre lo que está haciendo fase de compilación
Inferencia: Podemos omitir explícitamente dando Nombre de Tipo de Algo en código fuente, llamada Inferencia de tipos
. (Aunque se requiere en algunos casos excepcionales).Tipo Adscripción: Ser explícito sobre el tipo de algo se llama una indicación de tipo. Lo que diferencia que puede hacer?
ex: val x = 2: Byte
También ver: 1. Podemos dar explícitamente el tipo de retorno a nuestras funciones
def t1 : Option[Option[String]] = Some(None)
> t1: Option[Option[String]]
Otra manera de declarar esto podría ser:
def t2 = Some(None: Option[String])
> t2: Some[Option[String]]
Aquí no nos damos vuelta Option[Option[String]]
tipo de forma explícita y compilador inferimos como Some[Option[String]]
.
¿Por Some[Option[String]]
es porque utilizamos tipo adscripción en la definición.
-
Otra manera en que podemos utilizar la misma definición es:
def t3 = Some(None)
> t3: Some[None.type]
Esta vez no le dijo nada explícitamente el compilador (ni esta defi). Se infiere y nuestra definición como algunos [None.type]