Java, статические методы выдают в реальном случае. Реализация TableModel - PullRequest
2 голосов
/ 05 февраля 2012

Я хочу реализовать 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.

Как решить эту проблему, поддерживая достигнутый к настоящему времени хороший уровень инкапсуляции?

1 Ответ

4 голосов
/ 06 февраля 2012

Вы смешиваете модель и рассматриваете понятия. Ваша модель MyRow не должна знать, как она будет представлена, и поэтому она не должна знать, сколько существует столбцов, что они содержат и т.д. ).

Один из способов сделать это более аккуратно - заставить TableModel возвращать количество столбцов, а также реализовать getValueAt, вызывая членов вашего класса MyRow. Вы взглянули на реализацию по умолчанию (DefaultTableModel).

Теперь я не понимаю, почему вам нужно переопределить статические методы (что невозможно). Если вам нужны разные модели таблиц для разных объектов, которые наследуют друг друга, вы можете рассмотреть возможность создания разных моделей таблиц, которые наследуют друг друга одинаково.

...