I want to implement a TableModel, that will enable my existing data structure to be displayed by a JTable.
Say my data structure is a simple List
<MyRow>, where MyRow is:
public class MyRow {
String firstName;
String secondName;
}
My idea is that this class "should do its part" in being displayed, so i add it the following method, that simply maps each field to an index:
public Object getValueAt(int columnIndex) {
switch (columnIndex) {
case 0: return firstName;
case 1: return secondName;
default: return null;
}
}
At this point, the TableModel
implementation will simply be:
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);
}
}
Neat, isn't it? :-)
Ok, but return 2;
annoys me. In this "architecture" i have assigned to MyRow the rexposibility to represent a row, and so it should be MyRow that gives the number of columns. That because it provides the getValueAt(int columnIndex)
method that is related to the number of columns: columnsIndex<columnCount.
This piece of information may be asked even if there are no rows in the List
, so no instances of MyRow
. So the method to add to MyRow should be a static method:
public class MyRow {
...
public static int getColumnCount() { return 2; }
...
And the getColumnCount() method of MyModel will be simply modified accordingly:
public int getColumnCount() {
//return 2; //No more this *Encapsulation Violation*
return MyRow.getColumnCount();
}
Now MyRow contains all the data needed to represent a row. It is easy to show that: adding, removing or changing columns is just question of modifying MyRow.
Clean, isn't it? :-) :-)
The problem is that with static methods, i can't provide an abstract super-class for MyRow. This should be obvious, but to be sure:
public abstract class MyAbstractRow {
public static int getColumnCount() { return 0; }
}
then
public class MyRow extends MyAbstractRow{
String firstName;
String secondName;
public static int getColumnCount() { return 2; }
}
then i implement a "generic" MyData, that uses a MyAbstractRow:
public int getColumnCount() {
//return 2; //No more this *Encapsulation Violation*
return MyAbstractRow.getColumnCount();
}
This is resolved on the static type (so returns 0) because the getColumnCount of MyData doesn't even have a reference to the type i actually want to use as my concrete implementation of MyAbstractRow.
How to solve this problem, mantaining the good level of encapsulation achieved so far?