52 votes

Pourquoi java.util.Observable n'est pas une classe abstraite ?

Je viens de remarquer que java.util.Observable est une classe concrète. Puisque le but d'Observable est d'être étendu, cela me semble plutôt étrange. Y a-t-il une raison pour laquelle elle a été implémentée de cette façon ?

J'ai trouvé cet article qui dit que

L'observable est une classe concrète, donc la classe qui en dérive doit être déterminée au préalable, car Java ne permet qu'un seul héritage.

Mais ça ne l'explique pas vraiment pour moi. En effet, si Observable était abstrait, l'utilisateur serait obligé de déterminer la classe qui en dérive.

6 votes

Je pense que ça aurait dû être une interface. C'est l'un de ces domaines auxquels on n'a pas assez réfléchi.

4 votes

Il ne peut pas être une interface, car il doit garder la trace des observateurs qui lui ont été ajoutés.

0 votes

Question intéressante. Au début, je pensais qu'il pouvait être utilisé "simplement", mais comme setChanged() es protected il n'y a aucun moyen d'utiliser un simple Observable en dehors de l'objet java.util paquet.

113voto

Bohemian Points 134107

Il s'agit tout simplement d'un erreur que Observable est une classe du tout , abstraites ou non.

Observable aurait dû être un interface et le JDK aurait dû fournir une implémentation pratique (un peu comme List est une interface et ArrayList est une mise en œuvre)

Il y a pas mal d'"erreurs" en java, notamment :

Alors que sur le boîte à savon en termes de la langue elle-même, IMHO :

  • == devrait exécuter le .equals() (ce qui cause de nombreux maux de tête)
  • comparaison des identités == devrait être soit === comme javascript ou une méthode dédiée comme boolean isIdentical(Object o) parce que vous n'en avez presque jamais besoin !
  • < devrait exécuter compareTo(Object o) < 0 para Comparable (et de même pour les objets > , <= , >= )

1 votes

Eh bien, il demande "pourquoi n'est-elle pas abstraite" et non "pourquoi utilisent-ils une classe au lieu d'une interface ?" . Je pense qu'il est intéressé par la raison de conception (une fois que l'"erreur" est faite) de ne pas forcer l'utilisateur à hériter.

1 votes

Je suis en effet intéressé par la raison de la conception. Il se pourrait bien qu'il s'agisse d'une erreur.

3 votes

Il ne peut pas être une interface parce qu'il a une implémentation qui n'est pas triviale. une interface avec addObserver/removeObserver pourrait être décente mais honnêtement l'observateur aurait dû être générique (avec E comme paramètre pour la mise à jour)

31voto

edutesoy Points 3024

En première approche, on pourrait penser que cela est fait pour permettre à l'utilisateur d'utiliser la composition au lieu de l'héritage, ce qui est très pratique si votre classe hérite déjà d'une autre classe et vous ne pouvez pas non plus hériter de la classe Observable.

Mais si nous regardons le code source de Observable, nous voyons qu'il y a un drapeau interne

private boolean changed = false;

Elle est vérifiée à chaque fois que la fonction notifyObservers est invoquée :

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

Pero d'une classe composée par cet Observable, nous ne pouvons pas changer cet indicateur puisqu'il est privé et que les méthodes fournies pour le modifier sont protégées.

Cela signifie que l'utilisateur est obligé de sous-classer la classe Observable, et je dirais que l'absence du mot-clé "abstract" est juste une "erreur".

Je dirais que cette classe est un échec total.

0 votes

L'utilisateur peut sous-classer Observable et agréger cette sous-classe.

0 votes

Cette réponse a manqué un point. le changed est privé et il ne peut pas être défini dans une sous-classe également. Le fait est que Observable ont un setChanged et elle est protégée et peut donc être appelée dans les sous-classes, mais pas dans une classe de composition.

0 votes

Des raisons de compatibilité empêchent l'équipe de JavaSoft de changer Observable à une classe abstraite, car le code existant (mauvais code) qui instancie Observable directement échouerait avec un java.lang.InstantiationError . Néanmoins, on pourrait l'instancier directement et utiliser la réflexion pour invoquer la fonction setChanged() y clearChanged() ou de modifier directement l'état de l'indicateur modifié, pour autant que le gestionnaire de sécurité l'autorise.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X