¿Es este comportamiento esperado para String.containsOnly ()?
Aquí hay un código para ilustrar el problema.
String str1 = '';
System.debug(str1.containsOnly('W'));
Esperaría falsecomo resultado, pero sorprendentemente el resultado fue true. No entiendo por qué este es el caso considerando que una cadena vacía no contiene un 'W'carácter. ¿Es este comportamiento esperado o un error?
Editar : Después de las respuestas que he recibido hasta ahora, creo que necesito reformular mi pregunta y hacerla más fundamental. Al hacerlo, se responderá a la pregunta original.
Una suposición subyacente que estoy haciendo es que la documentación del método precedió y fue la base de la implementación del método y no al revés. Si cree que esta suposición es incorrecta, hágamelo saber.
Dejando así de lado cómo containsOnly()se implementa actualmente, ¿cómo se debe entender la documentación del método? Es más una cuestión de sentido o semántica que técnica. Esta es la descripción dada.
containsOnly (inputString) Devuelve verdadero si la cadena actual contiene caracteres solo de la secuencia de caracteres especificada y no otros caracteres; de lo contrario, devuelve falso.
Aquí están las posibles interpretaciones hasta ahora:
La cadena actual no contiene ningún carácter fuera de los caracteres de la cadena de entrada. (@PhilW)
La cadena actual contiene cualquiera de los caracteres en la cadena de entrada (
containsAny(inputString)) && interpretación 1. (Tengo entendido).
Hágame saber cómo entiende la documentación o la frase containsOnly y si tiene alguna otra interpretación plausible, la agregaré a la lista. Creo que se necesita cierto consenso al respecto antes de entrar en la implementación real del método.
Respuestas
Lógicamente, sí, porque la cadena vacía no contiene ningún carácter no permitido.
Los caracteres no permitidos son los que no se enumeran explícitamente en la especificación "única". Entonces, en este caso, es cualquier letra que no sea "W".
Si estuviera implementando este método yo mismo, haría algo como:
public Boolean containsOnly(String allowed) {
// "chars" is the internal array of characters in the string
for (Integer i = 0; i < chars.size(); i++) {
if (allowed.indexOfChar(chars[i]) < 0) {
return false;
}
}
return true;
}
El punto es que es una iteración compacta que busca caracteres no permitidos con salida anticipada según sea necesario y si no encuentra ningún carácter no permitido, simplemente devuelve verdadero.
No creo que este comportamiento pueda considerarse un error; es un resultado natural de verificar de una manera compacta y eficiente. También puede ver una cadena vacía como cero instancias del carácter 'W'. String.containsOnlyvolverá verdadero para:
- cero caracteres 'W' (la cadena vacía)
- un carácter 'W' (la cadena 'W')
- dos caracteres 'W' (la cadena 'WW')
- etc.
Si desea verificar que tiene una cadena no vacía y que solo tiene los caracteres especificados, adapte su código para hacer lo siguiente:
if (str1.isNotEmpty() && str1.containsOnly('W')) {
...
}
Me inclino a pensar que esto no es un error y es un comportamiento estándar, pero la documentación es, en el mejor de los casos, ambigua y no da indicaciones sobre cómo debería funcionar una cadena vacía . Se justifica una aclaración adicional dado que containsy containsOnlydevolver diferentes resultados en estos escenarios:
''.contains('W'); //false
''.containsOnly('W'); //true
Anexo : algunos ejemplos adicionales que muestran cómo esta función es más parecida a un conjunto que la containsque busca una subcadena en una cadena determinada:
'abab'.containsOnly('ab'); //true
'ab'.containsOnly('abab'); //true
'abab'.containsOnly('abcd'); //true
'abab'.contains('ab'); //true
'ab'.contains('abab'); //false
'abab'.contains('abc'); //false
La containsOnlyoperación debe definirse en términos matemáticos y tengo el presentimiento de que se implementa de esa manera. No existe estrictamente una operación como containsOnly( que yo sepa, no soy un matemático ), pero se puede llegar de dos maneras con las operaciones de conjunto estándar. Si toma la intersección (∩) de los dos conjuntos y la intersección es la misma que su primer operando, es true, lo que significa que los dos conjuntos se superponen por completo:
{A, B} ∩ {A, B} = {A, B}
{} ∩ {A, B} = {}
Pero las reglas del álgebra de conjuntos tratan un conjunto vacío de una manera única en el sentido de que todos los siguientes son equivalentes:
{} ∩ {A, B} ≡ {} ∩ {} ≡ {}
Esto explicaría por qué una cadena vacía, que es un 'conjunto' vacío de caracteres, siempre devolvería verdadero cuando se realiza la operación en ella. La intersección del conjunto vacío con cualquier otro conjunto (incluido otro conjunto vacío) es siempre el conjunto vacío.
Esa era una forma de implementar una containsOnlyfunción usando operaciones de conjuntos. El otro es usar la diferencia (\). Si la diferencia de dos conjuntos es la misma que la original, podría decir que el primer conjunto contiene solo el segundo conjunto. Nuevamente, el conjunto vacío se comporta de manera similar al uso de una intersección.
{A, B} \ {A} = {B}
{A, B} \ {A, B} = {} ≡ {} \ {A, B} = {} ≡ {} \ {} = {}
Mi suposición es que containsOnlyse implementa utilizando uno de estos métodos para su algoritmo y la documentación de la Stringclase debe actualizarse para reflejar la metodología actual del método (para que los futuros desarrolladores sean conscientes de los matices). O el método debe cambiarse para hacerse consistente contains.