¿Por qué no define CharSequence contiene (CharSequence)?

11

Esto se aplica tanto a Java SE como a Android, ya que los contratos son idénticos.

CharSequenceno define un contains(CharSequence)método Parece que no puedo encontrar un motivo, e incluirlo sería bastante útil, evitando la necesidad de llamar CharSequence#toString()para verificar una secuencia de caracteres.

Por ejemplo, en Android, los usuarios se ven obligados a llamar Editable#toString()para ver si contiene una secuencia de caracteres, aunque Editableimplementos CharSequence, que se pueden evitar si se CharSequencedefinen contains(CharSequence).

¿Cuál es la idea detrás de esta elección de diseño? ¿Es un descuido potencial o hay una razón de diseño para esto?

Vince Emigh
fuente

Respuestas:

10

El objetivo CharSequencees proporcionar una vista de solo lectura a una secuencia de caracteres, y eso es todo. Esta interfaz no proporciona manipulación de cadenas ni métodos de búsqueda. Esos están fuera de alcance.

El Principio de segregación de interfaz sugiere que los clientes de un tipo no deberían depender de métodos que no utilizan. Por lo tanto, una interfaz debe declarar solo el conjunto útil mínimo. Si un caso de uso diferente necesita métodos diferentes, debería haber una interfaz diferente.

Un cliente que solo necesita una fuente de caracteres probablemente no necesita métodos de búsqueda.

Por supuesto, es posible exagerar este Principio y terminar con mil pequeñas interfaces. Eso tampoco es bueno. Entonces, la CharSequenceinterfaz no solo contiene el mínimo charAt()y los length()métodos, sino también el método de conveniencia profundamente relacionado subSequence(). (Una secuencia de caracteres probablemente puede proporcionar una vista en una subsecuencia sin una copia de cadena, por lo que este debería ser un método de instancia). Especificar toString()está bien porque ese método se heredaría de todos modos Object. Los métodos chars()y codePoints()adaptar CharSequencea una Streaminterfaz. Debido a que estos son métodos predeterminados, no imponen requisitos adicionales para la implementación de clases CharSequence.

El CharSequencetipo es útil cuando un método necesita una fuente de caracteres genéricos sin especificar una implementación particular (por ejemplo, String vs. CharBuffer vs. StringBuilder). Los métodos String#join()y String#contains()son buenos ejemplos de uso de CharSequences.

No es necesario CharSequenceproporcionar un contains()método porque puede implementarse externamente. Si bien Java no tiene la conveniencia de los métodos de extensión de C #, un método estático es esencialmente lo mismo. Entonces en lugar de boolean Editable#contains(CharSequence needle)ti tendrías un static boolean contains(CharSequence haystack, CharSequence needle). Los algoritmos de búsqueda de cadenas son un tema informático bien estudiado. Diferentes algoritmos con diferentes compensaciones están fácilmente disponibles.

Otras lecturas:

amon
fuente
2
Usted menciona " Esta interfaz no proporciona ninguna manipulación de cadenas o métodos de búsqueda. Los que están fuera de su alcance. ", Pero containsno es un método de mutación, y no tiene métodos de búsqueda existe ( charAt), así que ¿cómo se aplica esto ?. Además, " Debido a que estos son métodos predeterminados, no imponen requisitos adicionales para las clases que implementan CharSequence ". ¿No se pudo containsimplementar como predeterminado a través de la impl return to String().contains(...), eliminando el requisito de que las clases se implementen?
Vince Emigh
1
@VinceEmigh Sí, contains()podría ser un método predeterminado. Si existiera, no debería implementarse en términos String#containssino al revés: String debería usar la implementación de CharSequence. El charAt()es diferente. No implementa un algoritmo de búsqueda, es una parte crucial de CharSequence: sin él, los contenidos no podrían copiarse en un tipo diferente String. Las secuencias son una parte crucial de Java8, y agregar estos métodos predeterminados está en línea con las adiciones a otras interfaces como Collection.
amon