2010-01-18 10 views
63

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 sintaxis y los efectos de su uso.¿Cuál es el propósito de las asignaciones de tipo en Scala?

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 

Respuesta

66

La asignación de tipo solo le dice al compilador qué tipo espera de una expresión, de todos los tipos válidos posibles.

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 aplica a "es una", o hay una conversión que se aplica en su alcance.

Por lo tanto, 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 Object, no como String. Como no hay restricciones que lo impidan y el tipo deseado es uno de los tipos ses, funciona.

Ahora, ¿por qué querrías eso? Considere 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 
<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 ascripting s en ss declaración, o que podría haber declarado ss 's Tipo ser 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 se compila:

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 tonto para usar un identificador de aquí en lugar de Nil. Y aunque solo podía 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 Scala 2.7 spec (Marzo 15, 2009 PROYECTO) tiene que decir sobre el tipo de adscripción:

Expr1 ::= ... 
     | PostfixExpr Ascription 

Ascription ::= ‘:’ InfixType 
      | ‘:’ Annotation {Annotation} 
      | ‘:’ ‘_’ ‘*’ 
26

Una posibilidad es cuando la red y cosas 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 también es una conversión en tiempo de ejecución (no manejada por el compilador) y podría dar lugar a algunas condiciones de sobre/subdesbordamiento interesantes.

+1

Heh, aprendí algo nuevo. Hago una cantidad desafortunada de cosas del protocolo de red. ¡Bueno saber! –

+10

¿Por qué no utilizar la sintaxis diaria? 'val x: Byte = 2' – Jerry101

0

Puede encontrar this thread iluminando, si es un poco intrincado a 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 compilación.

+0

:) Remití mi pregunta aquí para que se conservara; la respuesta que seleccioné es la de ese hilo que fue más clara para mí – davetron5000

+1

"Página no encontrada" actualice el enlace – samthebest

+0

Lo siento, acabo de ver esto. Hecho. –

0

Uso el tipo de adscripción 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. Desde Cero extiende Lista [Nada], utilizando 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) 
<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) 

Alternativamente, usted podría utilizar List.empty [Int] en lugar de Cero: Listado [Int].

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

edición: List.empty [A] se implementa como

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

(source)

Se trata efectivamente de una forma más detallada del Cero: Listado [A]

+0

¿Por qué no 'x.foldLeft [Lista [Int]] (Nil) ((acc, elem) => elem :: acc)'? –

0

Inferencia de tipos : 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 Ascripción: Ser explícito sobre el tipo de algo se llama una Asignación de tipo. ¿Qué diferencia puede hacer?

ejemplo: val x = 2: Byte

también vemos: 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 proporcionamos Option[Option[String]] tipo de devolución explícitamente y el Compilador lo dedujo como Some[Option[String]]. Por qué Some[Option[String]] es porque usamos la adscripción de tipo en la definición.

  1. Otra manera en que podemos utilizar la misma definición es:

    def t3 = Some(None)

    > t3: Some[None.type]

esta vez no lo dijo explícitamente al compilador cualquier cosa (ni esta defi). Y dedujo nuestra definición como Algunos [None.type]

Cuestiones relacionadas