51

I just noticed that java.util.Observable is a concrete class. Since the purpose of Observable is to be extended, this seems rather odd to me. Is there a reason why it was implemented this way?

I found this article which says that

The observable is a concrete class, so the class deriving from it must be determined upfront, as Java allows only single inheritance.

But that doesn't really explain it to me. In fact, if Observable were abstract, the user would be forced to determine the class deriving from it.

Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
S.L. Barth
  • 7,954
  • 71
  • 47
  • 62
  • 5
    I deally it should have been an interface. This is one of those areas that did not get enough thought. – Swaranga Sarma Sep 02 '11 at 09:22
  • 4
    It cannot be an interface, because it needs to keep track of the Observers that were added to it. – S.L. Barth Sep 02 '11 at 09:23
  • Interesting question. At first I thought it could be used "plain", but since `setChanged()` is `protected` there's no way to use a plain `Observable` object outside of the `java.util` package. – Joachim Sauer Sep 02 '11 at 09:26
  • 11
    "It cannot be an interface, because it needs to keep track of the Observers that were added to it." Well, that would be the job of the implementation for that interface. Just like Collection has a size() method without providing an implementation for it. – Thilo Sep 02 '11 at 09:27
  • The [javadoc for Observable](http://download.oracle.com/javase/7/docs/api/java/util/Observable.html) states that `It can be subclassed...` not must be. It is usable without subclassing, you will just need to do some more casts. – krock Sep 02 '11 at 09:29
  • @krock: Like Joachim said, it is not really that usable on its own, because you cannot call `setChanged` (except from a subclass). – Thilo Sep 02 '11 at 09:33
  • 13
    It is old. Really old. And we know of a lot of code in the older parts of Java that we would do better today. If they change it to `abstract` now it may break a lot of exiting applications (although I don't see any reason to instantiate `Observable`...). – Andreas Dolk Sep 02 '11 at 09:47
  • @Thilo: regarding the interface-vs-implementation: not only does Observable have to keep track of the Observers, it also contains the logic to notify them. If these two were left out of Observable, then the main responsibilities of Observable would be moved to the classes that implement it. – S.L. Barth Sep 02 '11 at 09:58
  • Yes, responsibility of implementing the interface properly is left to the implementing classes. I think if they designed it again, Observable would be an interface, and you'd have another class ObservableSupport that you could either subclass to get its implementation, or use as a delegate if you want to have a different parent class. – Thilo Sep 02 '11 at 10:02
  • 3
    What I was trying to say is that there really wouldn't be much point to an Observable interface. The implementation would almost always be the same. This is where it differs from Collection. But it would make sense if there was a default implementation available - the ObservableSupport class that you suggest . A bit like the KeyListener/KeyAdapter classes. – S.L. Barth Sep 02 '11 at 10:11
  • It should have been an interface. Ideally an AbstractObserver should implement a (simple) Subject interface (conform GoF). Then one can also use Subject to make other interfaces observable, which is now impossible. – avandeursen Dec 19 '11 at 11:40

2 Answers2

112

Quite simply it's a mistake that Observable is a class at all, abstract or otherwise.

Observable should have been an interface and the JDK should have provided a convenient implementation (much like List is an interface and ArrayList is an implementation)

There are quite a few "mistakes" in java, including:

While on the soapbox, in terms of the language itself, IMHO:

  • == should execute the .equals() method (this causes loads of headaches)
  • identity comparison == should either be === like javascript or a dedicated method like boolean isIdentical(Object o), because you hardly ever need it!
  • < should execute compareTo(Object o) < 0 for Comparable objects (and similarly for >, <=, >=)
lesmana
  • 22,750
  • 8
  • 73
  • 83
Bohemian
  • 365,064
  • 84
  • 522
  • 658
  • 1
    Well, he asks _"why isn't it abstract"_, and not _"why do they use a Class instead of an Interface"_. I think he is interested in the design reason (once the "mistake" is done) of not forcing the user to inherit. – Mr.Eddart Sep 02 '11 at 13:49
  • 1
    I am indeed interested in the design reason. It may well have been a mistake though. – S.L. Barth Sep 02 '11 at 14:27
  • 3
    it can't be an interface because it has an implementation that is non trivial. an interface with addObserver/removeObserver could be decent but honestly observer should have been generic (with E as the parameter for the update) – ratchet freak Sep 02 '11 at 16:42
  • 7
    @ratchet_freak List is an interface, so is Map. Do you think they are any less complex to implement than Observable? No - they aren't. Yet they are interfaces. The JDK should have provided an Observable interface and an implementation, just as it provides the Map interface and HashMap, and other, implementations. I agree about the generics part. – Bohemian Sep 02 '11 at 20:59
  • 6
    Seeing that this is not really an answer (but collecting lots of upvotes as people agree with this popular sentiment), it should be acommunity wiki. – Thilo Sep 06 '11 at 07:41
  • 3
    I can't agree about SQLException. It is akin to an IOException. Unless you abandon checked exceptions altogether, which is another entire topic, it should certainly be one of them. – user207421 Jul 14 '13 at 02:10
  • Don't forget that Throwable should have been an interface – Enerccio May 29 '17 at 06:57
  • Not to mention, InputStream and OutputStream should've been interfaces. – anacron Mar 23 '18 at 07:14
31

As a first approach, one could think that this is done to allow the user to use composition instead of inheritance, which is very convenient if your class already inherits from another class, and you cannot inherit from Observable class also.

But if we look to the source code of Observable, we see that there is an internal flag

private boolean changed = false;

That is checked everytime the notifyObservers is invoked:

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);
    }

But from a class composed by this Observable, we cannot change this flag, since it is private, and the methods provided to change it are protected.

This means that the user is forced to subclass the Observable class, and I would say that the lack of the "abstract" keyword is just a "mistake".

I would say that this class is a complete screwup.

Mr.Eddart
  • 9,190
  • 11
  • 45
  • 71
  • The user can subclass Observable and aggregate this subclass. – Micha Wiedenmann Dec 06 '12 at 15:42
  • This answer missed some point. the `changed` flag is private and it cannot be set in a subclass as well. The fact is that `Observable` do have a `setChanged` method and it is protected so can be called in subclasses, but not a composition class. – Earth Engine May 01 '13 at 00:58
  • Compatibility reasons prevent the JavaSoft team from changing `Observable` to an abstract class, as existing code (bad code) that instantiates `Observable` directly would fail with a `java.lang.InstantiationError`. Still, one could directly instantiate it and use reflection to invoke the `setChanged()` and `clearChanged()` methods, or directly change the state of the changed flag, so long as the security manager allows it. – gparyani Aug 18 '13 at 05:45