Почему java.util.Observable не абстрактный класс?

Я только заметил, что java.util.Observable - это конкретный класс. Поскольку цель Observable должна быть расширена, это кажется мне довольно странным. Есть ли причина, почему это было реализовано таким образом?

Я нашел эту статью, в которой говорится, что

Наблюдаемый - это конкретный класс, поэтому класс, вытекающий из него, должен быть определен заранее, поскольку Java допускает только одно наследование.

Но это на самом деле не объясняет это мне. Фактически, если Observable были абстрактными, пользователь был бы вынужден определить класс, вытекающий из него.

Ответ 1

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

Но если мы посмотрим на исходный код Observable, мы увидим, что есть внутренний флаг

private boolean changed = false;

Проверяется каждый раз при вызове notifyObservers:

public void notifyObservers(Object arg) {
        Object[] arrLocal;

    synchronized (this) {
        if (!changed) return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

Но из класса, составленного этим Observable, мы не можем изменить этот флаг, поскольку он является закрытым, а методы, предоставленные для его изменения, защищены.

Это означает, что пользователь вынужден подклассифицировать класс Observable, и я бы сказал, что отсутствие "абстрактного" ключевого слова - это просто "ошибка".

Я бы сказал, что этот класс является полным отвращением.

Ответ 2

Совсем просто ошибка, что Observable - это класс вообще, абстрактный или другой.

Observable должен был быть интерфейсом, и JDK должен был обеспечить удобную реализацию (так же, как List является интерфейсом, а ArrayList является реализацией)

В java существует немало "ошибок", в том числе:

  • java.util.Stack - это класс, а не интерфейс (например, Observable, плохой выбор).
  • java.util.Properties extends java.util.Hashtable (а не использует один)
  • java.util.Date класс немного беспорядок и не immutable!
  • класс java.util.Calendar - настоящий беспорядок
  • Нет типа unsigned 'byte' (это настоящая боль и источник многих ошибок низкого уровня)
  • java.sql.SQLException является checked exception
  • Массивы не используют Arrays.toString(array) в качестве значения по умолчанию toString() (сколько вопросов SO вызвало это?)
  • Cloneable не должен быть интерфейсом маркера; он должен иметь метод clone() и Object.clone() не должен существовать

Пока на soapbox, с точки зрения самого языка, IMHO:

  • == должен выполнить метод .equals() (это вызывает множество головных болей)
  • сравнение идентичности == должно быть либо ===, как javascript, или выделенный метод, например boolean isIdentical(Object o), потому что вам он вряд ли когда-либо понадобится!
  • < должен выполнить compareTo(Object o) < 0 для Comparable объектов (и аналогично для >, <=, >=)