Enquanto algumas pessoas podem odiar "métodos opcionais", em muitos casos podem oferecer semântica melhor do que interfaces altamente segregadas. Entre outras coisas, eles permitem as possibilidades de que um objeto possa adquirir habilidades ou características durante sua vida útil, ou que um objeto (especialmente um objeto de invólucro) talvez não saiba quando é construído quais habilidades exatas devem ser relatadas.
Embora eu dificilmente chame as classes de coleções Java de modelos de bom design, sugiro que uma boa estrutura de coleções inclua em sua base um grande número de métodos opcionais, além de maneiras de perguntar a uma coleção sobre suas características e habilidades . Esse design permitirá que uma única classe de wrapper seja usada com uma grande variedade de coleções sem ocultar acidentalmente as habilidades que a coleção subjacente possa possuir. Se os métodos não fossem opcionais, seria necessário ter uma classe de wrapper diferente para cada combinação de recursos que as coleções possam suportar, ou então alguns wrappers podem ser inutilizados em algumas situações.
Por exemplo, se uma coleção suportar escrever um item por índice ou anexar itens no final, mas não suportar a inserção de itens no meio, o código que deseja encapsulá-lo no wrapper que registraria todas as ações executadas nela precisaria de uma versão do wrapper de log que fornecia a combinação exata de habilidades suportadas ou, se não houvesse nenhum disponível, seria necessário usar um wrapper que suporta anexar ou gravar por índice, mas não ambos. Se, no entanto, uma interface de coleção unificada fornecesse todos os três métodos como "opcional", mas incluísse métodos para indicar quais métodos opcionais seriam utilizáveis, uma única classe de wrapper poderia manipular coleções que implementam qualquer combinação de recursos. Quando perguntado sobre quais recursos ele suporta, um wrapper pode simplesmente relatar o que a coleção encapsulada suportar.
Observe que a existência de "habilidades opcionais" pode, em alguns casos, permitir que coleções agregadas implementem certas funções de maneiras muito mais eficientes do que seria possível se as habilidades fossem definidas pela existência de implementações. Por exemplo, suponha que um concatenate
método tenha sido usado para formar uma coleção composta de duas outras, a primeira sendo uma ArrayList com 1.000.000 elementos e a última uma coleção de vinte elementos, que só poderia ser iterada desde o início. Se a coleção composta fosse solicitada para o 1.000.013 ° elemento (índice 1.000.012), ele poderia perguntar à ArrayList quantos itens continha (ou seja, 1.000.000), subtrair isso do índice solicitado (com 12), ler e pular doze elementos do segundo coleção e, em seguida, retorne o próximo elemento.
Em tal situação, mesmo que a coleção composta não tivesse uma maneira instantânea de retornar um item por índice, solicitar à coleção composta pelo 1.000.013º item ainda seria muito mais rápido do que ler 1.000.013 itens individualmente e ignorar todos, exceto o último 1.