Perché java.util.Observable non è una class astratta?

Ho appena notato che java.util.Observable è una class concreta. Poiché lo scopo di Observable deve essere esteso, mi sembra piuttosto strano. C’è una ragione per cui è stata implementata in questo modo?

Ho trovato questo articolo che dice questo

L’osservabile è una class concreta, quindi la class derivante da essa deve essere determinata in anticipo, poiché Java consente solo l’ereditarietà singola.

Ma questo non me lo spiega davvero. Infatti, se Observable fosse astratto, l’utente sarebbe costretto a determinare la class derivante da esso.

    Come primo approccio, si potrebbe pensare che ciò sia fatto per consentire all’utente di usare la composizione invece dell’ereditarietà, il che è molto conveniente se la class eredita già da un’altra class , e non si può ereditare anche dalla class Observable.

    Ma se guardiamo al codice sorgente di Observable, vediamo che c’è una bandiera interna

     private boolean changed = false; 

    Viene verificato ogni volta che viene richiamato 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); } 

    Ma da una class composta da questo Osservabile, non possiamo cambiare questo flag , dato che è privato, e i metodi forniti per cambiarlo sono protetti.

    Ciò significa che l’utente è costretto a sottoclass la class Observable, e direi che la mancanza della parola chiave “abstract” è solo un “errore”.

    Direi che questa lezione è un completo fallimento.

    Semplicemente è un errore che Observable è una class, astratta o meno.

    Observable avrebbe dovuto essere un’interfaccia e il JDK avrebbe dovuto fornire un’implementazione conveniente (molto simile a List è un’interfaccia e ArrayList è un’implementazione)

    Ci sono alcuni “errori” in Java, tra cui:

    • java.util.Stack è una class, non un’interfaccia (come Observable, bad choice)
    • java.util.Properties estende java.util.Hashtable (anziché utilizzarne uno)
    • La class java.util.Date è un po ‘confusa e non è immutabile !
    • La class java.util.Calendar è un vero casino
    • Nessun tipo di ‘byte’ senza segno (questo è un vero dolore e la fonte di molti bug di basso livello)
    • java.sql.SQLException è un’eccezione controllata
    • Gli array non usano Arrays.toString(array) come default toString() (quante domande SO hanno causato?)
    • Cloneable non dovrebbe essere un’interfaccia marcatore; dovrebbe avere il metodo clone() e Object.clone() non dovrebbe esistere

    Mentre sei sul soapbox , in termini del linguaggio stesso, IMHO:

    • == dovrebbe eseguire il metodo .equals() (questo causa un sacco di mal di testa)
    • il confronto dell’identity framework == dovrebbe essere === come javascript o un metodo dedicato come boolean isIdentical(Object o) , perché non ne hai quasi mai bisogno!
    • < deve eseguire compareTo(Object o) < 0 per oggetti Comparable (e allo stesso modo per > , < = , >= )