Pregunta

Me he estado preguntando si las conversiones de transparente implícito son realmente una buena idea y si sería mejor usarlas implícitas más, um, explícitamente . Por ejemplo, supongamos que tengo un método que acepta un Date como parámetro y tengo una conversión implícita que convierte un String en un Date :

implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)

private def foo(d: Date)

Entonces, obviamente, puedo llamarlo con una conversión transparente implícita :

foo("20090910")

¿Sería mejor hacer el hecho de que estoy convirtiendo la cadena en una fecha más explícita?

class DateString(val s: String) { 
  def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s) 
}

implicit def str2datestr(s: String) : DateString = new DateString(s)

Entonces el uso se parece más a:

foo("20090910".toDate)

La ventaja de esto es que queda más claro más adelante sobre lo que está sucediendo. Me han sorprendido algunas veces con conversiones transparentes de implícito que debo conocer (opción a Iterable ¿alguien?) y este uso aún nos permite aprovechar el poder de implícito s.

¿Fue útil?

Solución

Creo que cuanto más " explícito " La forma de hacer conversiones implícitas es mucho mejor en términos de legibilidad que la totalmente transparente, al menos en este ejemplo.

En mi opinión, el uso de implícito es totalmente transparente desde el tipo A al tipo B está bien cuando puede siempre ver un objeto de tipo A para poder ser usado siempre que sea necesario un objeto de tipo B . Por ejemplo, la conversión implícita de un String a un RandomAccessSeq [Char] siempre tiene sentido: un String siempre puede verse, conceptualmente, como una secuencia de caracteres (en C, una cadena es solo una secuencia de caracteres, por ejemplo). Una llamada a x.foreach (println) tiene sentido para all String s.

Por otra parte, las conversiones más explícitas deben usarse cuando un objeto de tipo A puede a veces ser usado como un objeto de tipo B . En su ejemplo, una llamada a foo (" barra ") no tiene sentido y produce un error. Como Scala no ha verificado las excepciones, una llamada a foo (s.toDate) indica claramente que puede haber una excepción lanzada ( s puede no ser una fecha válida). Además, foo (" bar " .toDate) parece claramente incorrecto, mientras que usted necesita consultar la documentación para ver por qué foo (" bar ") puede estar equivocado. Un ejemplo de esto en la biblioteca estándar de Scala son las conversiones de String s a Int s, a través del método toInt de RichString wrapper ( String s puede verse como Int s, pero no todo el tiempo ).

Otros consejos

Cuando haces una conversión implícita de X a Y (como la conversión de String a Date arriba), esencialmente estás diciendo que, si tuvieras el control total sobre la escritura de X en primer lugar, habrías implementado X o ser una subclase de Y.

Si tiene sentido que X implemente Y, entonces agregue la conversión. Si no es así, entonces tal vez no sea apropiado. Por ejemplo, tiene sentido que String implemente RandomAccessSeq [Char], pero tal vez no tenga sentido que String implemente Date (aunque String implementa StringDate parece estar bien).

(Llego un poco tarde, y Flaviu tiene una excelente respuesta, pero quería agregar un comentario sobre cómo pienso acerca de las implicaciones).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top