Problème héritage et classes abstraites
Bonjour,
version courte:
j'aimerais réussir à créer une classe A dont hériteraient des classes A1, A2, etc, ainsi qu'une classe B dont hériteraient des classes B1, B2, etc, avec la relation "un tableau d'objets de classe Bi est membre de Ai". Ce que je voudrais, c'est au final obtenir quelque chose qui me permette de fabriquer une tableau d'objets de classes A1, A2 (etc) et que je puisse parcourir ce tableau en appelant, pour chaque type d'objet (A1, A2, etc) la méthode "toto" de la classe B correspondante. Ce que je veux bien sur, c'est que ces méthodes "toto" soient différentes dans chaque classe type B. Donc pour l'instant, j'ai créé deux jeux de classes comprenant une classe abstraite et plusieurs classes en héritant (A et A1, A2 etc ainsi que B et B1, B2 etc). Dans mon code, chaque classe type A (A, A1,A2, etc) a un membre qui est un tableau d'objets de type B (B, B1, B2 etc respectivement). Malheureusement, ça ne fonctionne pas: lorsque je crée mes objets A1, A2 etc, les tableaux d'objets B1, B2 membres sont bien créés, mais lorsque l'exécution du code se poursuit, les champs de classe Bi dans mes objets de classe Ai sont null.
Est-ce que quelqu'un a compris mon problème ?
Plus fort: est-ce que quelqu'un a une solution à me proposer ?
Je pourrais si vous le voulez poster une version plus détaillée de mon problème, n'hésitez pas à me demander des détails si ce n'est pas clair pour vous, c'est très important pour moi.
Merci
sébastien
Pour essayer d'être plus précis
version détaillée:
Mon but c'est de simuler l'évolution des gènes d'un individu. Il y a plusieurs types de gènes, qui sont répartis sur des chromosomes: chaque type de gène peut être voisin avec n'importe quel autre type de gène. De plus chaque type de gène a une action spécifique sur la survie de l'individu. Du coup ce que je veux, c'est un tableau contenant des objets de différentes classes, chacune de ces classes ayant un champ et une méthode qui portent le même nom mais qui sont différents, de telle sorte que je puisse appeler cette méthode pour tous mes objets dans le tableau et qu'elle me fasse un calcul spécifique au type d'objet dans lequel elle a été appelée.
Ci-dessous je détaille ce que j'ai fait.
J'ai écrit une classe Individual (désolé le programme est en anglais), avec un champ Genome (un tableau d'objets de classe Locus). La classe Locus est une classe abstraite dont dérivent plusieurs classes (Locus_type_0 et Locus_type-1 par exemple).
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
public Class Individual{
public Individual() {
this.genome = new Genome();
}
Genome genome; // génome = tableau d'objets de classe Gene
double W; // probabilité de survie de l'individu: affectée
// différemment suivant la classe du gène (G1, G2 etc)
double trait;
}
public class Genome {
/** Creates a new instance of Genome */
public Genome() {
// Genome.nb_chrom: nombre de chromosomes; Genome.nb_loci[i]: nombre de locus pour le chromosome i
// ces locus peuvent être de différentes classes, avec des effets différents sur la survie de l'individu
this.loci = new Locus[Genome.nb_chrom][];
for (int which_pair = 0; which_pair < Genome.nb_chrom; which_pair ++) {
this.loci[which_pair] = new Locus[ Genome.nb_loci[which_pair] ];
for (int which_locus = 0; which_locus < Genome.nb_loci[which_pair]; which_locus ++){
switch (Genome.genetic_map[which_pair][which_locus]){
case 0: this.loci[which_pair][which_locus] = new Locus_type_0();
break;
case 1: this.loci[which_pair][which_locus] = new Locus_type_1();
}
}
}
public Locus[][] loci;
}
public abstract class Locus {
public Locus() {
}
Allele[] alleles;
public abstract void calculSurvie(Individual ind);
}
public class Locus_type_0 extends Locus {
public Locus_type_0() {
this.alleles = new Allele_type_0[2];
}
Allele_type_0[] alleles;
public void calculSurvie(Individual ind){
if (this.alleles[0] == this.alleles[1]) {
ind.type_0_W *= this.alleles[0].s;
// "s" est un champ spécifique de la classe Allele_type_0
}
else {
// faire autre chose;
}
}
}
public class Locus_type_1 extends Locus {
public Locus_type_1() {
this.alleles = new Allele_type_1[2];
}
Allele_type_1[] alleles;
public void calculSurvie(Individual ind){
ind.trait = (this.alleles[0].effect_on_trait + this.alleles[1].effect_on_trait);
// "effect_on_trait" est un champ spécifique de la classe Allele_type_1
}
} |
Les différences entre les classes héritant de Locus sont visibles dans une méthode (calculSurvie) et un champ (alleles).
- champ alleles: c'est un tableau d'objets. La classe abstraite Locus a un tableau d'objets de classe abstraite Allele, la classe Locus_type_0 a un champ de classe Allele_type_0 dérivée de Allele, etc
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
public abstract class Allele {
public Allele() { }
byte type;
}
public class Allele_type_0 extends Allele{
public Allele_type_0() {
this.type = 0;
this.s = 1.0f;
this.weight = Allele_type_0.WT_weight;
this.mutated = 0;
}
static float WT_weight;
double s;
double weight;
byte mutated;
}
public class Allele_type_1 extends Allele {
public Allele_type_1(int generation, int made_while_mutation, float expectancy) {
this.type = 1;
this.effect_on_trait = expectancy;
}
float effect_on_trait;
} |
-méthode calculSurvie: chaque classe dérivéée de la classe Locus surcharge la méthode abstraite calculSurvie de telle sorte que le calcul fait dans cette méthode est spécifique à celle-ci et aux champs disponibles dans la classe Allele correspondante (Allele_type_0 etc), voir premier extrait de code.
Le problème que je rencontre, c'est que lorsque je crée un individu, tout est bien fabriqué comme je le voudrais jusqu'aux constructions des objets de classes Locus et dérivées. Mais ensuite, je veux affecter des objets dans le champ "alleles" de chaque locus en faisant un truc du genre
Code:
1 2 3
|
machin.alleles[0] = new Allele_type_i ();
// i = 0, 1 etc selon le type d'objet que je veux mettre à cet endroit |
et ça me génère systématiquement une NullPointerException. Après quelques recherches, je me suis aperçu que le champ alleles est Null, alors que sa création dans le constructeur de Locus_type{0,1,etc} s'était bien passée.
Personnellement, je me dis que c'est lié au fait que le champ "alleles" est déclaré dans la classe Locus et dans les classes dérivées, d'où un conflit potentiel.
Pensez-vous que c'est la bonne explication ?
Auriez-vous une idée qui me permette de faire ce que je voudrais ?
J'espère que cette fois c'était compréhensible, même si c'est compliqué....
merci
séébastien