我正在尝试这样做:
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
参数。
如何做到这一点?
我也在这里问follow up question。如果你能回答这个问题,我将不胜感激。
此question是相关的,但仅在假定类具有默认构造函数的情况下才相关。
答案 0 :(得分:5)
已经说过,你不能用new
创建T的实例,所以
我会使用工厂模式或原型模式
所以你的构造函数看起来像
public BaseTable(int rows, int cols, LineFactory factory)
具有适当的工厂实例。
在你的情况下,我更喜欢Prototype Pattern,因为你的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());
}
答案 1 :(得分:3)
不应该这样做的好理由是,你不能强迫子类实现某个构造函数。对于接口的实现来说非常明显,因为它们不包含构造函数的契约。
如果你的真实或抽象类BaseTable
有一个构造函数BaseTable(int columns)
,那么带有单个列的虚构子类VectorTable
就不需要实现它,并且可以做一些像
public VectorTable(int intialValue) {
super(1);
this.initialValue = initialValue;
}
首先,你不知道T
是否实现了构造函数,其次,你不知道构造函数是否具有相同的目的(它应该在正确的代码中真正具有它! !)
所以我认为,更好的解决方案是将参数化部分从构造函数移动到单独的(final?)方法中,使用默认构造函数创建实例并在之后调用该初始化方法。
如果您想确保所有BaseTable子类始终都能正确初始化,您可以考虑实现BaseTableFactory
。
修改强>
并且new T()
(实例化默认构造函数)也是不可能的,因为没有类可以强制来实现可访问的默认构造函数。我仍然认为,工厂模式是你最好的朋友。
答案 2 :(得分:1)
您需要使用Factory界面:
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);
P.S。这不是我原来的解决方案。我很久以前就找到了它并在我的代码中使用它。不幸的是,我找不到原创想法的链接......
答案 3 :(得分:-1)
简单!
使用静态工厂方法而不是构造函数:
public static <T extends TableEntry> newInstance(int rows, int cols) {
return new BaseTable<T>(rows, cols);
}
实例化类型
BaseTable<Number> = BaseTable.newInstance(10, 20);