Почему CharSequence не определяет содержит (CharSequence)?

11

Это относится как к Java SE, так и к Android, поскольку контракты идентичны.

CharSequenceне определяет contains(CharSequence)метод. Кажется, я не могу найти причину, по которой, и в том числе, было бы весьма полезно предотвратить необходимость вызова CharSequence#toString()для проверки последовательности символов.

Например, в Android пользователи вынуждены звонить, Editable#toString()чтобы узнать, содержит ли он последовательность символов, хотя и Editableреализует CharSequence, чего можно избежать, если он CharSequenceопределен contains(CharSequence).

Какая идея стоит за этим выбором дизайна? Это потенциальный недосмотр или есть причина для этого?

Винс Эмиг
источник

Ответы:

10

Смысл в CharSequenceтом, чтобы предоставить представление только для чтения для последовательности символов, и все. Этот интерфейс не предоставляет никаких манипуляций со строками или методов поиска. Это вне области.

Принцип разделения интерфейса предполагает, что клиенты типа не должны зависеть от методов, которые они не используют. Поэтому интерфейс должен объявлять только минимальный полезный набор. Если для другого варианта использования требуются другие методы, должен быть другой интерфейс.

Клиент, которому нужен только источник символов, вероятно, не нуждается в методах поиска.

Конечно, возможно переусердствовать с этим принципом и получить тысячу маленьких интерфейсов. Это тоже не хорошо. Таким образом, CharSequenceинтерфейс не только содержит минимальный charAt()и length()методы, но также и глубоко связанный метод удобства subSequence(). (CharSequence может обеспечить представление подпоследовательности без копирования строки, поэтому это должен быть метод экземпляра). Указание toString()ОК, потому что этот метод все равно будет унаследован от Object. Методы chars()и codePoints()адаптировать CharSequenceк Streamинтерфейсу. Поскольку это методы по умолчанию, они не накладывают дополнительных требований на реализацию классов CharSequence.

CharSequenceТипа полезно , когда метод необходим общий источник символов без указания конкретной реализации (например , строка против CharBuffer против StringBuilder). String#join()И String#contains()методы являются хорошими примерами использования CharSequenceс.

Нет необходимости CharSequenceпредоставлять contains()метод, потому что он может быть реализован извне. Хотя в Java нет удобных методов расширения C #, статический метод - это, по сути, одно и то же. Так что вместо boolean Editable#contains(CharSequence needle)тебя будет static boolean contains(CharSequence haystack, CharSequence needle). Алгоритмы поиска строк являются хорошо изученной темой информатики. Различные алгоритмы с различными компромиссами легко доступны.

Дальнейшее чтение:

Амон
источник
2
Вы упоминаете « Этот интерфейс не обеспечивает строку манипуляции или методы поиска. Это из области видимости. », Но containsэто не метод мутации, и там же существуют методы , поиск ( charAt), так как это относится ?. Кроме того, « Поскольку это методы по умолчанию, они не налагают дополнительных требований к классам, реализующим CharSequence. » - Не может containsбыть реализовано по умолчанию через impl return to String().contains(...), устраняя требование к классам для реализации?
Винс Эми
1
@ VinceEmigh Да, contains()может быть методом по умолчанию. Если он существует, он не должен быть реализован в терминах, String#containsа наоборот: String должен использовать реализацию CharSequence. Это charAt()другое. Он не реализует алгоритм поиска, это важная часть CharSequence: без него содержимое не может быть скопировано в другой тип, например String. Потоки являются важной частью Java8, и добавление этих методов по умолчанию соответствует дополнениям к другим интерфейсам, таким как Collection.
Амон