2009-06-24 18 views
0

継承に問題があります。私は、親クラスと子クラスの単一インスタンスで必要なことを行うことができます - 期待どおり、親クラスのメソッドは子クラスのインスタンスで正常に動作します。継承 - 親クラスの配列と子クラスの配列 - キャスト

しかし、子クラスの配列を格納できるように、親クラスの配列を使用するクラスを拡張する方法はわかりません。申し訳ありませんが、コードのサイズについては、私は小さなスニペットで問題を明確にすることができるとは思わない。

この問題の解決方法はありますか?

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"); 
    } 
} 

答えて

2

あなたはGenericsStatsArrayのためにジェネリック医薬品を使用する必要があります。

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

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

    //... 
} 

あなたは一般的な要素を(すなわち、あなたはnew T()を言うことができない)インスタンス化することはできませんので、あなたはおそらく、あなたのクラスに抽象ファクトリー・メソッドが必要になります。

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

ありがとう:

はこのような何かを!私は誤って正しい単語(generic)を使用していました。 –

+0

配列 "gs"を作成する方法を提案しますか?実際のTの型を知っているので、子クラスはそれをしなくてはならないと思う。実行時にTを知らないので、親クラスはできない。 P.S.あなたのCPUStatsArrayでは、 "T"はおそらく "CPUStats"でなければなりません。 – newacct

+0

@newacct:そうです。私は最近C#コードを書いているので、タイプ消去について忘れてしまった。あなたは子クラスにそれをさせることができますが、代わりにGenericStatsの配列を使うこともできます。 –