Por que CharSequence define contains (CharSequence)?

11

Isso se aplica ao Java SE e Android, pois os contratos são idênticos.

CharSequencenão define um contains(CharSequence)método. Não consigo encontrar uma razão para isso, e incluí-lo seria bastante útil, evitando a necessidade de ligar CharSequence#toString()para verificar uma sequência de caracteres.

Por exemplo, no Android, os usuários são obrigados a ligar Editable#toString()para ver se ele contém uma sequência de caracteres, embora Editableimplementos CharSequence, que podem ser evitados se CharSequencedefinidos contains(CharSequence).

Qual é a ideia por trás dessa escolha de design? É uma supervisão em potencial ou existe uma razão de design para isso?

Vince Emigh
fonte

Respostas:

10

O objetivo CharSequenceé fornecer uma exibição somente leitura para uma sequência de caracteres, e é isso. Essa interface não fornece nenhum método de manipulação ou pesquisa de strings. Esses estão fora do escopo.

O Princípio de Segregação de Interface sugere que os clientes de um tipo não devem depender dos métodos que não usam. Portanto, uma interface deve declarar apenas o conjunto útil mínimo. Se um caso de uso diferente precisar de métodos diferentes, deve haver uma interface diferente.

Um cliente que precisa apenas de uma fonte de caracteres provavelmente não precisa de métodos de pesquisa.

É claro que é possível exagerar neste princípio e acabar com mil pequenas interfaces. Isso também não é bom. Portanto, a CharSequenceinterface não contém apenas o mínimo charAt()e os length()métodos, mas também o método de conveniência profundamente relacionado subSequence(). (Um CharSequence provavelmente pode fornecer uma exibição em uma subsequência sem uma cópia de cadeia, e é por isso que esse deve ser um método de instância). A especificação toString()está correta porque esse método seria herdado de qualquer maneira Object. Os métodos chars()e codePoints()adaptam a CharSequencea uma Streaminterface. Por serem métodos padrão, eles não impõem requisitos adicionais para a implementação de classes CharSequence.

O CharSequencetipo é útil quando um método precisa de uma fonte de caracteres genérica sem especificar uma implementação específica (por exemplo, String vs. CharBuffer vs. StringBuilder). Os métodos String#join()e String#contains()são bons exemplos de uso de CharSequences.

Não é necessário CharSequencefornecer um contains()método, pois ele pode ser implementado externamente. Embora o Java não tenha a conveniência dos métodos de extensão do C #, um método estático é essencialmente a mesma coisa. Então, em vez de boolean Editable#contains(CharSequence needle)você teria um static boolean contains(CharSequence haystack, CharSequence needle). Os algoritmos de busca de strings são um tópico bem estudado da ciência da computação. Diferentes algoritmos com diferentes tradeoffs estão prontamente disponíveis.

Leitura adicional:

amon
fonte
2
Você menciona " Esta interface não fornece qualquer manipulação corda ou métodos de procura. Esses são fora do escopo. ", Mas containsnão é um método de mutação, e não existem métodos de busca ( charAt), assim como isso se aplica ?. Além disso, " Como esses são métodos padrão, eles não impõem requisitos adicionais para as classes que implementam CharSequence " . - Não pôde containsser implementado como padrão por meio do impl return to String().contains(...), removendo o requisito de implementação das classes?
Vince Emigh
1
@VinceEmigh Sim, contains()poderia ser um método padrão. Se existiu, não deve ser implementado em termos de, String#containsmas o contrário: String deve usar a implementação CharSequence. O charAt()é diferente. Ele não implementa um algoritmo de busca, é uma parte crucial do processo CharSequence: sem ele, o conteúdo não pode ser copiado para um tipo diferente String. Os fluxos são uma parte crucial do Java8, e a adição desses métodos padrão está alinhada com adições a outras interfaces, como Collection.
amon