EDIT 2:paramètres de type Utilisation et mixins à Scala
j'ai réussi à obtenir la sécurité de type que je voulais dans mon exercice avec une combinaison en utilisant numération romaine de mixins et des paramètres de type avec le code ci-dessous. En substance ce qu'il fait est après avoir importé tout dans RomanNumerals
je peux écrire L X V I
, mais pas L L
ou X L X
parce que je reçois une erreur de compilateur de type incompatibilité (puisque ceux-ci seraient des combinaisons illégales de chiffres romains). Maintenant, je me demande si cette façon d'utiliser les traits, les mixins et les paramètres de type est considérée comme correcte ou si j'abuse du langage pour ainsi dire :) Y a-t-il un meilleur moyen d'obtenir le même type de sécurité avec un système plus simple? code?
object RomanNumerals {
trait Numeral {
def num:Int
}
trait NumeralI[N<:Numeral] extends Numeral
trait NumeralV[N<:Numeral] extends NumeralI[N] {
def I = new RomanNumeral[Numeral](1 + this.num) with Numeral
def II = new RomanNumeral[Numeral](2 + this.num) with Numeral
def III = new RomanNumeral[Numeral](3 + this.num) with Numeral
}
trait NumeralX[N<:Numeral] extends NumeralV[N] {
def IV = new RomanNumeral[Numeral](4
+ this.num) with Numeral
def V = new RomanNumeral[NumeralI[Numeral]](5
+ this.num) with NumeralV[NumeralI[Numeral]]
def IX = new RomanNumeral[Numeral](9
+ this.num) with Numeral
}
trait NumeralL[N<:Numeral] extends NumeralX[N] {
def X = new RomanNumeral[NumeralV[Numeral]](10
+ this.num) with NumeralX[NumeralV[Numeral]]
def XX = new RomanNumeral[NumeralV[Numeral]](20
+ this.num) with NumeralX[NumeralV[Numeral]]
def XXX = new RomanNumeral[NumeralV[Numeral]](30
+ this.num) with NumeralX[NumeralV[Numeral]]
}
class RomanNumeral[T <: Numeral](val num:Int) {
override def toString = num toString
def apply[N >: T <: Numeral](rn:NumeralI[N]) =
new RomanNumeral[Numeral](rn.num + num) with Numeral
def apply[N >: T <: Numeral](rn:NumeralV[N]) =
new RomanNumeral[NumeralI[Numeral]](rn.num
+ num) with NumeralV[NumeralI[Numeral]]
def apply[N >: T <: Numeral](rn:NumeralX[N]) =
new RomanNumeral[NumeralV[Numeral]](rn.num
+ num) with NumeralX[NumeralV[Numeral]]
def apply[N >: T <: Numeral](rn:NumeralL[N]) =
new RomanNumeral[NumeralX[Numeral]](rn.num
+ num) with NumeralL[NumeralX[Numeral]]
}
val I = new RomanNumeral[NumeralI[Numeral]](1) with NumeralI[Numeral]
val II = new RomanNumeral[NumeralI[Numeral]](2) with NumeralI[Numeral]
val III = new RomanNumeral[NumeralI[Numeral]](3) with NumeralI[Numeral]
val IV = new RomanNumeral[NumeralI[Numeral]](4) with NumeralI[Numeral]
val V = new RomanNumeral[NumeralI[Numeral]](5) with NumeralV[NumeralV[Numeral]]
val IX = new RomanNumeral[NumeralI[Numeral]](9) with NumeralI[Numeral]
val X = new RomanNumeral[NumeralV[Numeral]](10) with NumeralX[NumeralX[Numeral]]
val XX = new RomanNumeral[NumeralV[Numeral]](20) with NumeralX[NumeralX[Numeral]]
val XXX = new RomanNumeral[NumeralV[Numeral]](30) with NumeralX[NumeralX[Numeral]]
val XL = new RomanNumeral[NumeralV[Numeral]](40) with NumeralX[NumeralX[Numeral]]
val L = new RomanNumeral[NumeralX[Numeral]](50) with NumeralL[NumeralL[Numeral]]
}
EDIT:
question plus de base Victors answere. Ok, mais que se passe-t-il si j'ajoute des limites supérieures et inférieures au paramètre de type afin que B soit un trait? Par exemple.
trait Bar
class Foo[T<:Bar](n:Int) {
def apply[B >: T <: Bar](f:Foo[B]) = {
new Foo[B](n + f.n) with B
}
}
Ou peut-être B
peut encore être une classe dans ce cas? Que faire si je sais que l'argument f s'applique aussi est de type Foo[B] with B
? Existe-t-il un moyen d'utiliser cela pour mixer B
avec le type de retour?
QUESTION ORIGINAL CI-DESSOUS
Je veux mélanger dans un trait que je reçois en tant que paramètre de type lorsque je crée un objet à Scala:
class Foo(val num:Int) {
def withM[B](foo:Foo) = new Foo(foo.num) with B
}
Il en résulte une erreur de compilation:
error: class type required but B found
def withM[B](foo:Foo) = new Foo(foo.num) with B
^
J'ai aussi essayé:
class Foo(val num:Int) {
def withM[B](foo:Foo) = new Foo(foo.num) with classOf[B]
}
Mais cela ne fonctionne pas:
error: not found: type classOf
def withM[B](foo:Foo) = new Foo(foo.num) with classOf[B]
^
est-il someway pour contourner cela? Alors que le type de retour de withM devient Foo with B
où B
est le paramètre de type passé à withM
Edité la question avec un peu plus d'informations/nouvelle question :) –