2009-06-24 8 views
0

J'ai des problèmes avec l'héritage. Je peux faire ce dont j'ai besoin avec des instances uniques de la classe parent et de la classe enfant - comme prévu, les méthodes de la classe parent fonctionnent correctement avec les instances de la classe enfant. Mais, je ne vois pas comment étendre une classe qui utilise un tableau de la classe parente, d'une manière qui me permette de stocker un tableau de la classe enfant. Désolé pour la taille du code, mais je ne pense pas pouvoir clarifier le problème avec un extrait plus petit.Héritage - Tableaux de la classe parente et tableaux de la classe enfant - diffusion

Existe-t-il un moyen efficace de résoudre ce problème?

public class TestIn { 
    public static void main(String args[]) { 
     CPUStats c = new CPUStats(); 
     c.set(4,5);  // OK 
     c.dump(); 
     CPUStatsArray ca = new CPUStatsArray(24); 
     ca.set(3, 21, 25);  // Data for hour 3 = 21 and 25 
     ca.dump();    // Fails 
    } 
} 

class GenericStats { 
    long s[];   // The stats, e.g. [0]=CPU% and [1]=Mem% 
    // snip, more members 

    // Constructor setting statistics to all zeros 
    public GenericStats(int n) { 
     s = new long[n]; 
    } 

    void set(long ... v) { 
     s = new long[v.length]; 
     for (int i = 0 ; i < v.length ; i++) 
      s[i] = v[i]; 
    } 

    void dump() { 
     for (int i = 0 ; i < s.length ; i++) 
      System.out.print(" [" + i + "] = " + s[i]); 
     System.out.println(); 
    } 
    // snip, a few useful methods 
} 

class CPUStats extends GenericStats { 
    public CPUStats() { 
     super(2); 
    } 
    void dump() { 
     System.out.println("CPU% = " + s[0] + ", and Mem% = " + s[1]); 
    } 
} 

// class WhateverStats extends GenericStats { 
// .... 
// } 

// So far so good, I can use the useful methods of GenericStats on a CPUStats object 

// Now I want an array of sets of statistics, e.g. for 24 sets of stats, one per hour 
class GenericStatsArray { 
    GenericStats gs[]; 
    int gslen;  // Length of s in each gs[] (not the length of gs[]) 

    public GenericStatsArray(int numSets, int inlen) { 
     gs = new GenericStats[numSets]; // Problem caused by using the base class here 
     gslen = inlen; 
    } 

    // Set values for element (e.g. hour) n 
    void set(int n, long ... v) { 
     if (gs[n] == null) 
      gs[n] = new GenericStats(gslen); 
     gs[n].s = new long[v.length]; 
     for (int i = 0 ; i < v.length ; i++) 
      gs[n].s[i] = v[i]; 
    } 

    void dump() { 
     System.out.println("GenericStatsArray"); 
     for (int i = 0 ; i < gs.length ; i++) 
      if (gs[i] != null) { 
       System.out.print("Array element [" + i + "] "); 
       gs[i].dump(); 
      } 
     System.out.println("End GenericStatsArray\n"); 
    } 
} 

class CPUStatsArray extends GenericStatsArray { 
    public CPUStatsArray(int numSets) { 
     super(numSets, 2); 
    } 
// Set values for element (e.g. hour) n 
    void set(int n, long ... v) { 
     assert (v.length == 2); 
     super.set(n, v); 
    } 
    void dump() { 
     System.out.println("CPUStatsArray"); 
     for (int i = 0 ; i < gs.length ; i++) 
      if (gs[i] != null) { 
       CPUStats c = (CPUStats) gs[i];  // This fails, 'GenericStats cannot be cast to CPUStats' 
       System.out.print("Array element [" + i + "] "); 
       c.dump(); 
      } 
     System.out.println("End CPUStatsArray\n"); 
    } 
} 

Répondre

2

Vous devez utiliser Génériques pour votre GenericsStatsArray:

public class GenericStatsArray<T extends GenericStats> { 
    GenericStats[] gs; 
    int gslen; 

    public GenericStatsArray(int numSets, int inlen) { 
    gs = new GenericStats[numSets]; 
    gslen = inlen; 
    } 

    //... 
} 

Vous aurez probablement besoin d'une usine méthode abstraite dans votre classe, puisque vous ne pouvez pas instancier un élément générique (par exemple, vous ne pouvez pas dire new T()).

quelque chose comme ça:

public abstract class GenericStatsArray<T extends GenericStats> { 
// ... 
    protected abstract T NewT(int gslen); 
    // ... 
    gs[n] = NewT(gslen); // was: gs[n] = new GenericStats(gslen); 
} 

public class CPUStatsArray extends GenericStatsArray<CPUStats> { 
    protected CPUStats NewT(int gslen){ 
    return new CPUStats(gslen); 
    } 
} 
+0

Merci! J'ai même accidentellement utilisé le mot correct (générique). –

+0

Comment proposez-vous de créer le tableau "gs"? Je suppose que la classe enfant devra le faire, car elle connaît le type réel de T. La classe parente ne le peut pas, car elle ne connaît pas T à l'exécution. P.S. Dans votre CPUStatsArray, le "T" devrait probablement être "CPUStats" – newacct

+0

@newacct: Vous avez raison. J'ai récemment écrit du C# -code, donc j'avais oublié le type-effacement. Vous pouvez laisser la classe enfant le faire, mais vous pouvez également utiliser un tableau de GenericStats à la place. –

Questions connexes