2010-04-07 6 views
8

Dans Scala v 2.7.7Scala paramètres de type de passage à objet

J'ai un fichier avec

class Something[T] extends Other 

object Something extends OtherConstructor[Something] 

Cela jette l'erreur:

class Something takes type parameters
object Something extends OtherConstructor[Something] {

Cependant, je ne peux pas faire ce

object Something[T] extends OtherConstructor[Something[T]] 

Il lance une erreur:

error: ';' expected but '[' found.

Est-il possible d'envoyer des paramètres de type à l'objet? Ou devrais-je changer et utiliser simplement un autre constructeur

Répondre

3

Un objet doit avoir un type concret. La construction d'objet Scala n'est pas une exception à cette règle.

Une définition est valable

object Something extends OtherConstructor[Something[T]] { } 

T est un peu concrets.

4

Vous pouvez utiliser:

object Something extends OtherConstructor[Something[_]] 

Vous serez naturellement limités par une de type existentiel sans limite supérieure en place au lieu d'un type concret. Cette solution peut ne pas avoir de sens et vous pourriez avoir besoin d'un objet par type de béton T, pour les T qui vous intéressent, par ex.

object StringSomething extends OtherConstructor[Something[String]] 

Mais ce qui a le (possible) inconvénient que StringSomething n'est pas l'objet compagnon de Something.

Cependant, mon conseil serait ne pas commencer à déconner sur la conception des API génériques (en particulier ceux autoréférentielles comme ci-dessus), sauf si vous avez vraiment, vraiment savez ce que vous faites. Il se terminera presque certainement en larmes et il y a beaucoup de CORE Java API qui sont terribles à cause des génériques de façon ont été ajoutés (l'API RowSorter sur JTable étant un exemple)

+0

L'API APT est bien aussi: 'Liste \t getAnnotationMirrors() '(http://java.sun.com/javase/6/docs/api/javax/lang/model/element/Element.html#getAnnotationMirrors%28%29) ;-) –

1

Merci pour les réponses

object Something extends OtherConstructor[Something[_]] 

semble être la compilation (bien que je n'ai pas encore à courir/vérifier que :-))

@oxbow_lakes, j'ai suivi vos conseils - d'éviter le système de type - jusqu'à maintenant, mais je dois le faire !!! J'étudie les types existentiels, le type d'effacement et tout cela, mais il est encore pas dans ma prise :-(

1

Vous pouvez résoudre le problème général d'avoir besoin object Foo[T] en déplaçant le paramètre de type aux méthodes object Foo:

class Foo[T](t1: T, t2: T) 

object Foo { 
    def apply[T](x: T): Foo[T] = new Foo(x, x) 
    def apply[T](x: T, y: T): Foo[T] = new Foo(x, y) 
} 

Si vous avez vraiment besoin d'un objet par T, vous pouvez faire une classe, et est le retour compagnon sans type il d'appliquer.

class Foo[T](t1: T, t2: T) 

class FooCompanion[T] { 
    def apply(x: T): Foo[T] = new Foo(x, x) 
    def apply(x: T, y: T): Foo[T] = new Foo(x, y) 
} 

object Foo { 
    def apply[T] = new FooCompanion[T] 
} 

object demo extends App { 
    val x: Foo[Double] = Foo.apply.apply(1.23) // this is what is really happening 
    val y: Foo[Int] = Foo[Int](123)    // with the type both apply calls are automatic 
} 

Notez cette re-construire le Foo [T ] un compagnon à chaque appel, vous voudriez le garder léger et apatride.

Une solution explicite le problème ci-dessus:

class Other 

class OtherConstructor[O <: Other] { 
    def apply(o: O): O = o // constructor 1 in base class 
} 

class Something[T](value: T) extends Other 

class SomethingConstructor[T] extends OtherConstructor[Something[T]] { 
    def apply(o: T, s: String) = new Something[T](o) // constructor 2 in subclass 
} 

object Something { 
    def apply[T] = new SomethingConstructor[T] // the "constructor constructor" method 
} 

object demoX extends App { 
    val si = new Something(123) 
    val sd = new Something(1.23) 

    val si1: Something[Int] = Something[Int](si)     // OtherConstructor.apply 
    val sd1: Something[Double] = Something[Double](1.23, "hello") // SomethingConstructor[Double].apply 
} 
Questions connexes