Я хочу реализовать TableModel, которая позволит моей существующей структуре данных отображаться в JTable.
Скажем, моя структура данных проста: List
, где 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
Эта часть информации может быть запрошена, даже если в List
нет строк, поэтому нет экземпляров MyRow
. Поэтому метод для добавления в MyRow должен быть статическим:
public class MyRow {
...
public static int getColumnCount() { return 2; }
...
И метод getColumnCount () MyModel будет просто соответствующим образом изменен:
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), потому что getColumnCount MyData даже не имеет ссылки на тип, который я на самом деле хочу использовать в качестве моей конкретной реализации MyAbstractRow.
Как решить эту проблему, поддерживая достигнутый к настоящему времени хороший уровень инкапсуляции?