4

我正在尝试这样做:

public class BaseTable<T extends TableEntry>

{

    protected int mRows;
    protected int mCols;
    protected ArrayList<T> mEntries;

    public BaseTable(int rows, int cols)
    {
        mRows = rows;
        mCols = cols;
        mEntries = new ArrayList<T>();
        for (int i = 0; i < rows; i++)
        {
            mEntries.add(new T(cols)); //this obv. doesn't work
        }
    }
}

实例化泛型本身就已经够难了,但更难的是T这里没有默认构造函数,它的构造函数中只有一个int参数。

如何才能做到这一点?


我也在这里问了一个后续问题。如果您也能回答这个问题,我将不胜感激。

这个问题是相关的,但仅在假定类具有默认构造函数的情况下才相关。

4

4 回答 4

5

已经说过,你不能用 来创建 T 的实例new,所以我会使用工厂模式或原型模式

所以你的构造函数看起来像 public BaseTable(int rows, int cols, LineFactory factory)一个适当的工厂实例。

在您的情况下,我更喜欢原型模式,因为您的 TableEntry 对象可能非常轻量级。您的代码如下所示:

public BaseTable(int rows, int cols, T prototype)
{       
  mRows = rows;
  mCols = cols;
  prototype.setColumns(cols);
  mEntries = new ArrayList<T>();
  for (int i = 0; i < rows; i++)
  {
    @SuppressWarnings("unchecked")
    T newClone = (T)prototype.clone();
    mEntries.add(newClone); //this obv. does work :)
  }
}

public static void main(String[] args)
{
  new BaseTable<SimpleTableEntry>(10, 2, new SimpleTableEntry());
}
于 2010-01-21T11:26:22.597 回答
3

应该这样做的充分理由是,您不能强制子类实现某个构造函数。接口的实现非常明显,因为它们不包含构造函数的合同。

如果你的真实或抽象类BaseTable有一个构造函数BaseTable(int columns),那么具有单列的虚构子类VectorTable就不需要实现它,并且可能会做一些不好的事情,比如

public VectorTable(int intialValue) {
  super(1);
  this.initialValue = initialValue;
}

因此,首先,您根本不知道是否T实现了构造函数,其次,您不知道构造函数是否具有相同的目的(它确实应该在正确的代码中具有相同的目的!!

所以我认为,更好的解决方案是将参数化部分从构造函数移动到单独的(最终?)方法中,使用默认构造函数创建实例,然后立即调用该初始化方法。

BaseTableFactory如果您想确保所有 BaseTable 子类始终正确初始化,您可能会考虑实现一个。

编辑

而且new T()(实例化默认构造函数)也是不可能的,因为不能强制任何类实现可访问的默认构造函数。我仍然认为,工厂模式是你最好的朋友。

于 2010-01-21T07:22:23.813 回答
1

您需要使用工厂接口:

public interface TableEntryFactory<T extends TableEntry>{
 public T create (int cols);
}

你还需要为每个“类型 T”的类创建一个工厂:

// for every class of type T
public class SpecialTableEntry extends TableEntry{
   SpecialTableEntry(int cols){
      ...
   }
}

// make a factory creating instance of this class
public class SpecialTableEntryFactory implements TableEntryFactory<SpecialTableEntry> {
   @Override
   public SpecialTableEntry create (int cols){
       return new SpecialTableEntry(cols);
   }
}

您的代码将如下所示:

public class BaseTable<T extends TableEntry>

{

protected int mRows;
protected int mCols;
protected ArrayList<T> mEntries;

public BaseTable(int rows, int cols, TableEntryFactory<T> tableFactory)
{
    mRows = rows;
    mCols = cols;
    mEntries = new ArrayList<T>();
    for (int i = 0; i < rows; i++)
      {
        mEntries.add(tableFactory.create(cols)); //this should work now
      }
  }
}


你可以这样称呼它:

TableEntryFactory<SpecificTableEntry> myFactory = new SpecificTableEntryFactory();
BaseTable<?> table = new BaseTable<SpecificTableEntry>(rows,cols,myFactory);


PS这不是我原来的解决方案。我很久以前在某个地方找到了它,并在我的代码中使用了它。不幸的是,我找不到原始想法的链接...

于 2012-09-14T16:19:05.647 回答
-1

简单的!

使用静态工厂方法而不是构造函数:

public static <T extends TableEntry> newInstance(int rows, int cols) {
    return new BaseTable<T>(rows, cols);
}

实例化类型

BaseTable<Number> = BaseTable.newInstance(10, 20);
于 2010-01-21T23:20:55.997 回答