【问题标题】:Inheritance - Arrays of parent class and arrays of child class - casting继承 - 父类数组和子类数组 - 强制转换
【发布时间】:2009-06-24 08:19:34
【问题描述】:

我遇到了继承问题。我可以使用父类和子类的单个实例来做我需要的事情 - 正如预期的那样,父类的方法可以很好地处理子类的实例。

但是,我看不到如何扩展使用父类数组的类,以允许我存储子类数组。对代码的大小感到抱歉,但我认为我不能用较小的 sn-p 来说明问题。

有没有巧妙的办法解决这个问题?

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

【问题讨论】:

    标签: java generics inheritance


    【解决方案1】:

    您应该为您的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);
      }
    }
    

    【讨论】:

    • 您建议如何创建数组“gs”?我猜子类必须这样做,因为它知道 T 的实际类型。父类不能,因为它在运行时不知道 T。附言在您的 CPUStatsArray 中,“T”应该是“CPUStats”
    • @newacct:你是对的。我最近大部分时间都在写 C# 代码,所以我忘记了类型擦除。你可以让子类来做,但你也可以只使用一个 GenericStats 数组来代替。
    猜你喜欢
    • 2012-04-21
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    相关资源
    最近更新 更多