Certaines personnes peuvent détester les "méthodes optionnelles", mais dans de nombreux cas, elles peuvent offrir une meilleure sémantique que des interfaces hautement séparées. Entre autres choses, ils permettent à un objet de gagner des capacités ou des caractéristiques au cours de sa vie, ou qu’un objet (en particulier un objet wrapper) ne sache pas quand il est construit quelles capacités exactes il doit signaler.
Bien que j'appelle difficilement les classes de collection Java comme étant des modèles de bonne conception, je suggérerais qu'un bon cadre de collections devrait inclure à sa base un grand nombre de méthodes facultatives ainsi que des moyens de demander à une collection ses caractéristiques et ses capacités . Une telle conception permettra à une seule classe wrapper d'être utilisée avec une grande variété de collections sans occulter accidentellement les capacités que la collection sous-jacente pourrait posséder. Si les méthodes n'étaient pas facultatives, il serait alors nécessaire de disposer d'une classe de wrapper différente pour chaque combinaison de fonctions pouvant être gérées par les collections, sinon certaines enveloppes seraient inutilisables dans certaines situations.
Par exemple, si une collection prend en charge l'écriture d'un élément par index ou l'ajout d'éléments à la fin, mais ne prend pas en charge l'insertion d'éléments au milieu, le code souhaitant l'encapsuler dans un wrapper qui enregistrerait toutes les actions effectuées sur celui-ci nécessiterait une version. du wrapper de journalisation qui fournissait la combinaison exacte des capacités prises en charge, ou si aucune n'était disponible, devrait utiliser un wrapper prenant en charge l'ajout ou l'écriture par index mais pas les deux. Si, toutefois, une interface de collection unifiée fournissait les trois méthodes en tant que "facultatives", mais incluait ensuite des méthodes pour indiquer laquelle des méthodes facultatives serait utilisable, une seule classe d'encapsuleur pourrait gérer des collections qui implémenteraient n'importe quelle combinaison de caractéristiques. Lorsqu'on lui demande quelles fonctionnalités il prend en charge, un wrapper peut simplement signaler tout ce que la collection encapsulée prend en charge.
Notez que l'existence de "capacités facultatives" peut dans certains cas permettre aux collections agrégées d'implémenter certaines fonctions de manière beaucoup plus efficace que si les capacités étaient définies par l'existence d'implémentations. Par exemple, supposons qu'une concatenate
méthode soit utilisée pour former une collection composite à partir de deux autres, le premier d'entre eux étant un ArrayList avec 1 000 000 d'éléments et le dernier étant une collection de 20 éléments pouvant uniquement être itérée dès le début. Si la collection composite était demandée pour le 1 000 013e élément (index 1 000 012), elle pourrait demander à ArrayList combien d'éléments elle contenait (c.-à-d. 1 000 000), soustrayez celle-ci de l'index demandé (donnant 12), lisez et ignorez 12 éléments du deuxième collection, puis renvoie l'élément suivant.
Dans une telle situation, même si la collection composite ne dispose pas d'un moyen instantané de retourner un élément par index, le demander à la collection composite pour le 1 000 013e élément serait toujours beaucoup plus rapide que de lire 1 000 013 éléments individuellement et d'ignorer tous les éléments sauf le dernier. un.