J'utilise des types abstraits et je rencontre des problèmes pour que le compilateur Scala unifie deux types qui doivent être identiques. Ce sont mes définitions:Incompatibilité de type avec les types abstraits
trait Chromosome {
type Gene
val size : Int
def apply(idx : Int) : Gene
def update(idx : Int, g : Gene)
def indices = Range(0, size-1)
}
trait Individual {
type Fitness
implicit protected val ord: Ordered[Fitness] = implicitly[Ordered[Fitness]]
val chromosome : Chromosome
def size : Int = chromosome.size
def apply(idx : Int) : chromosome.Gene = chromosome.apply(idx)
def update(idx : Int, g : chromosome.Gene) = chromosome.update(idx, g)
protected var _fitness : Fitness = _
def fitness : Fitness = _fitness
def fitness_=(f : Fitness):Unit = _fitness = f
}
case class ArrayChromosome(size : Int) extends Chromosome {
implicit protected val tag : ClassTag[Gene] = implicitly[ClassTag[Gene]]
protected val xs : Array[Gene] = new Array[Gene](size)
def apply(idx : Int) = xs(idx)
def update(idx : Int, g : Gene) = xs(idx) = g
}
abstract class ArrayIndividual(size : Int) extends Individual {
val chromosome = ArrayChromosome(size)
}
class MyIndividual(size : Int) extends ArrayIndividual(size) {
type Gene = Int
type Fitness = Double
}
object Test extends App {
val i1 = new MyIndividual(10)
i1.fitness = 10.5
i1.chromosome(0) = 6
print(i1)
}
A savoir, le problème est dans cette ligne:
i1.chromosome(0) = 6
et l'erreur de type est:
Error:(75, 22) type mismatch;
found : Int(6)
required: abstractTypes.Test.i1.chromosome.Gene
i1.chromosome(0) = 6
Il semble que le compilateur ne parvient pas à unifier i1.chromosome.Gene
avec Int
.
J'ai deux questions:
- Est-il possible d'aider le compilateur à unifier les deux types? Permettez-moi maintenant de supposer que j'ai supprimé la ligne fautive et que j'ai défini correctement
toString
pourIndividual
s. Pourquoi puis-je obtenir unjava.lang.NullPointerException
lors de l'exécutionTest
. Il semble que l'erreur est liée àGene
ClassTag
, mais je ne suis pas sûr.
Code de réponse à @ som-snytt:
abstract class ArrayIndividual(size : Int) extends Individual {
type Gene
implicit protected def tag2: ClassTag[Gene]
val chromosome = new ArrayChromosome(size) {
type Gene = ArrayIndividual#Gene
protected val tag : ClassTag[Gene] = tag2
}
}
class MyIndividual(size : Int) extends ArrayIndividual(size) {
type Fitness = Double
type Gene = Int
implicit protected val tag2 : ClassTag[Gene] = implicitly[ClassTag[Gene]]
override def toString = s"${super.toString} $chromosome"
}
Merci pour votre réponse, mais le type gène doit être abstraite en classe ArrayChromosome et ne se défini plus loin dans les sous-classes étendant celui-ci. Je suppose que je pourrais ajouter un paramètre de type, mais est-il possible de résoudre le problème d'unification sans un tel paramètre? – pepeStck
C'est ce que je voulais dire par le commentaire sur tag. Je vais ajouter un exemple de code. –
Notez le val paresseux. –