2011-11-07 10 views
11

Después de haber creado un nuevo tipo mezclando en ObservableSet con un HashSet, esperaba reemplazar y luego poder usar el nuevo tipo para crear un nuevo instancia como en "foo" a continuación. Pero esto no se compila, aunque el uso de la forma larga original del tipo parece estar bien (como se muestra en "barra", a continuación).Crear una instancia de un alias tipo provoca el error "tipo de clase requerido"

¿Es esto solo una característica del lenguaje o he hecho algo tonto?

package whatever 

import collection.mutable._ 
object Whatever { 

    type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] 
    class X 


    def foo { 
     new ObservableHashSet[X] 
    } 

    def bar { 
    new HashSet[X] with ObservableSet[X] 
    } 
} 

El error es ..

error: class type required but scala.collection.mutable.HashSet[scala.Whatever.X] with scala.collection.mutable.ObservableSet[scala.Whatever.X] found 
new ObservableHashSet[X] 

Respuesta

13

La versión abreviada es que ha creado un alias de tipo para un tipo estructural (que no se puede crear una instancia).

Ésta es una versión simplificada de lo que ha hecho (no funciona):

scala> import collection.mutable._ 
import collection.mutable._ 

scala> type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] 
defined type alias ObservableHashSet 

scala> new ObservableHashSet[String] 
<console>:12: error: class type required but scala.collection.mutable.HashSet[String] with scala.collection.mutable.ObservableSet[String] found new ObservableHashSet[String] 

Ahora, el error no tener algún sentido, y vamos a tratar de explicar por qué. Está definiendo un alias de tipo para algo que no es un tipo concreto (o, como dice el mensaje de error, no es un "tipo de clase"), por lo que no puede crear una instancia de él con new .

Pero esto (con un paso intermedio en el que hacemos crear un tipo de clase) funciona:

scala> class ObservableHashSet[T] extends HashSet[T] with ObservableSet[T] 
defined class ObservableHashSet 

scala> type obs[T] = ObservableHashSet[T] 
defined type alias obs 

scala> new obs[String] 
res1: ObservableHashSet[String] = Set() 

Entonces, la pregunta es: ¿por qué Scala permite crear un alias de tipo que no se puede crear una instancia? Bueno, type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] es un tipo estructural. Aunque, como ha visto en el primer fragmento de código, no puede crear una instancia de este, puede seguir usándolo: p. poner una restricción estructural en un argumento de una función.

Echale un vistazo:

scala> type ObservableHashSet[T] = HashSet[T] with ObservableSet[T] 
defined type alias ObservableHashSet 

scala> def test(obsHashSet: ObservableHashSet[String]) : String = {"bingo!"} 
test: (obsHashSet: ObservableHashSet[String])String 

scala> test(new HashSet[String] with ObservableSet[String]) 
res4: String = bingo! 

pero si tratamos de llamar a prueba con un argumento que no se ajuste al tipo estructural se obtiene una coincidencia de tipos:

scala> test(new HashSet[String]) 
<console>:13: error: type mismatch; 
found : scala.collection.mutable.HashSet[String] 
required: ObservableHashSet[String] 
+0

Gracias Paulo. Creo que estaba pensando en "tipo" como una especie de sustitución de macro ... Leeré un poco más sobre tipos estructurales. thx – Richard

+0

@Richard: gracias por la pregunta. Tampoco sabía la respuesta antes de preguntar y experimentar con "tipo" fue instructivo. –

Cuestiones relacionadas