2012-08-07 16 views
11

Quiero utilizar un tipo abstracto en lugar de un parámetro de tipo.constructores de la clase Scala y tipos abstractos

en mis clases genéricas constructor, quiero tener un parámetro de tipo genérico, pero el código no se compila:

class SomeOtherClass(val s: S){ 
    type S 
} 

es "no encontrado: Tipo S" El error del compilador Scala

Si utilizo un parámetro de tipo en lugar de un tipo abstracto, entonces funciona:

class SomeClass[T](val t: T){ 
    //... 
} 

obliga Scala que yo use un parámetro de tipo en lugar de un tipo abstracto, si yo quiero tener una parámetro genérico en el constructor?

¿Hay alguna otra manera de hacerlo?

Respuesta

3

En ese caso, se ve forzado a utilizar parámetros de tipo genérico. Puedes solucionarlo declarando el tipo fuera de la clase, pero luego necesitarías crear una instancia del contenedor y luego del objeto y se pondría muy rápido.

trait FooDef { 
    type T 
    class Foo(val x: T) 
} 
val ifd = new FooDef { type T = Int } 
val ifoo = new ifd.Foo(5) 
val sfd = new FooDef { type T = String } 
val sfoo = new sfd.Foo("hi") 
def intFoos(f: fd.Foo forSome { val fd: FooDef {type T = Int} }) = f.x + 1 
0

¿Cómo debe saber el compilador qué tipo debe usar allí? O bien, debe especificar el tipo directamente, lo que no tendría mucho sentido, o usar un genérico. Hay una manera de hacerlo funcionar, pero no creo que te sirva.

class SomeClass(s: SomeClass#S) { 
    type S 
} 

Pero como SomeClass # S no está definido, no hay ninguna instancia de este.

+0

Bastante curioso, esto le permitirá crear instancias 'new SomeClass (5.asInstanceOf [SomeClass # S]) {type S = Int}'. Tenga en cuenta que no hay seguridad, S aún no está definido en el reparto. – Kaito

+0

Entonces, básicamente, para hacerlo bien, ¿necesito ver las otras dos respuestas? –

+0

@AntKutschera sí. – Nicolas

0

Quizás quieras algo como esto? De esta forma, puede tener varias instancias de AbstractFooFactory produciendo cada una Foo s con un valor diferente para s.

trait AbstractFooFactory { 
    type S 
    def makeFoo(s:S):Foo 
    class Foo(val s:S) {} 
} 

object StringFooFactory extends AbstractFooFactory { 
    override type S = String 
    override def makeFoo(s:String) = new Foo(s) 
} 

val b = StringFooFactory.makeFoo("bar") 
val s:String = b.s 
1

Cuando no se especifica el tipo de resumen, su clase debe ser abstracta. Entonces no necesitas el parámetro en absoluto. El equivalente con un tipo abstracto sería:

abstract class SomeOtherClass { 
    type S 
    val s: S 
} 

A continuación, en el uso in situ:

val x = new SomeOtherClass { 
    type S = String 
    val s = "abc" 
} 

Sin el parámetro, la clase abstracta aquí es equivalente a un rasgo. Es mejor usar un rasgo porque es menos restrictivo (solo puedes extender una clase base).

Cuestiones relacionadas