我想实现一个TableModel,它将使我的现有数据结构能够由JTable显示。
假设我的数据结构是一个简单的 List
< MyRow> ,其中MyRow是:
public class MyRow {
String firstName;
String secondName;
}
我的想法是这个类“应该在显示中发挥作用”,所以我添加了以下方法,它只是将每个字段映射到索引:
public Object getValueAt(int columnIndex) {
switch (columnIndex) {
case 0: return firstName;
case 1: return secondName;
default: return null;
}
}
此时,TableModel
实施将只是:
public class MyModel extends AbstractTableModel {
ArrayList<MyRow> list = new ArrayList<MyRow>();
public int getRowCount() {return list.size();}
public int getColumnCount() {return 2;}
public Object getValueAt(int rowIndex, int columnIndex) {
return list.get(rowIndex).getValueAt(columnIndex);
}
}
干净,不是吗? :-)
好的,但return 2;
让我烦恼。在这个“架构”中,我已经为MyRow分配了表示行的可行性,因此它应该是MyRow,它给出了列数。这是因为它提供了与列数相关的getValueAt(int columnIndex)
方法:columnsIndex&lt; columnCount。
即使List
中没有行,也可能会询问此信息,因此没有MyRow
的实例。因此添加到MyRow的方法应该是静态方法:
public class MyRow {
...
public static int getColumnCount() { return 2; }
...
MyModel的getColumnCount()方法将相应地进行相应的修改:
public int getColumnCount() {
//return 2; //No more this *Encapsulation Violation*
return MyRow.getColumnCount();
}
现在,MyRow包含所有表示行所需的数据。很容易证明:添加,删除或更改列只是修改MyRow的问题 干净,不是吗? :-) :-)
问题是,使用静态方法,我无法为MyRow提供抽象超类。 这应该是显而易见的,但可以肯定:
public abstract class MyAbstractRow {
public static int getColumnCount() { return 0; }
}
然后
public class MyRow extends MyAbstractRow{
String firstName;
String secondName;
public static int getColumnCount() { return 2; }
}
然后我实现了一个“泛型”MyData,它使用MyAbstractRow:
public int getColumnCount() {
//return 2; //No more this *Encapsulation Violation*
return MyAbstractRow.getColumnCount();
}
这是在静态类型上解析的(因此返回0),因为MyData的getColumnCount甚至没有对我实际想要用作MyAbstractRow的具体实现的类型的引用。
如何解决这个问题,保持到目前为止所取得的良好封装水平?
答案 0 :(得分:4)
您正在混合模型和视图概念。你的模型MyRow不应该知道它将如何表示,所以它不应该知道有多少列,它们包含什么等等...这就是你遇到这个问题的原因(使用静态方法来知道列数)。
更干净地执行此操作的一种方法是让TableModel返回列数,并通过调用MyRow类的成员来实现getValueAt。您是否看过默认实现(DefaultTableModel)。
现在我不明白为什么你需要覆盖静态方法(这是不可能的)。如果您需要为不同的对象提供不同的表模型,那么您可以考虑创建以相同方式相互继承的不同表模型。