2011-08-31 12 views

Respuesta

3

No oculta la creación de un tipo. Básicamente enmascara el uso de la reflexión para comprobar sus restricciones estructurales en tiempo de compilación e invocar someMethod en el tiempo de ejecución.

Por ejemplo, si usted tiene:

class Foo(t: MyClass {def someMethod:String}) { 
    def CallSomeMethod = t.someMethod 
} 

Esto significa que el constructor de la clase Foo acepta una camiseta de MiClase tipo que también tiene un algunMetodo (donde el algunMetodo podría ser mezclado en MiClase a través de un rasgo). Usted podría tener:

class MyClass {} 
trait WithSomeMethod {def someMethod = "hello"} 

y, a continuación, podría crear Foo así:

val mc = new MyClass with WithSomeMethod 
val foo = new Foo(mc) 
println(foo.CallSomeMethod) // prints "hello" 

ahora, cuando se crea new Foo(mc) el compilador utiliza la reflexión para comprobar que mc es un MiClase que también tiene un algunMetodo . La llamada real foo.CallSomeMethod también funciona a través de la reflexión.

ahora (toleradme, Estoy llegando a su pregunta real ...) haciendo como lo hizo:

type T = MyClass {def someMethod:String} 

sólo se está creando un alias de tipo, no un tipo concreto. Una vez que tenga T define de esa manera, se puede definir como Foo:

class Foo(t: T) { 
    def CallSomeMethod = t.someMethod 
} 

esto es equivalente a la definición de Foo dada anteriormente. Acabas de crear un alias T que se puede reutilizar en otros lugares donde podrías haber usado MyClass {def someMethod:String}. No se genera ningún tipo de T real y el compilador todavía usa la reflexión cada vez que se refiere a T, para comprobar la restricción estructural que tiene un Método algo definido, y aún genera código basado en la reflexión para invocar algún Método.

+0

Gracias, entonces el uso de tal restricción estructural tan lenta como la reflexión en java? Y el rasgo es una mejor opción en esa luz. – yura

+0

sí, los tipos estructurales tienen un impacto en el rendimiento debido a la reflexión. –

3

No crea un rasgo, solo un alias de tipo, lo que significa que cada vez que se refiera a T, se refiere de hecho al MyClass {def someMethod:String}. Sin embargo, puede anular la declaración de tipo con un rasgo:

trait A 

class B { 
    type T <: A 
} 

class SubB { 
    trait T extends A 
} 
+0

Mi pregunta era qué está realmente oculto por esta sintaxis de Tipo. – yura

+0

Una respuesta mía fue: un alias tipo. – Nicolas

3

Considere esto: una clase no tiene un tipo estructural. El tipo de una clase siempre es una clase. Un rasgo produce una interfaz. El tipo de objeto singleton también es una clase.

¿Y dónde aparecen los tipos estructurales? Como tipos de parámetros y variables.

Por ejemplo, puedo decir def f(s: { def size: Int }), o val r: { def close(): Unit }.

Ahora, ¿cómo aparecen estos tipos como bytecode? Al igual que cualquier otro tipo que no sea compatible con JVM (como los propios genéricos de Java), son borrados.

Así, en lo que todos los demás (es decir, no Scala) se refiere, los tipos de s y r anteriores son java.lang.Object.

Para la propia Scala, se almacena cierta información adicional en una anotación, que proporciona la información exacta sobre estos tipos ya que Scala los entiende.

Cuestiones relacionadas