def conversion scala implicit

conversion - Opciones de uso implícito de Scala



scala implicit conversion (2)

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

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

Entonces, obviamente, puedo llamar a esto con una conversión implicit transparente:

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 claro más adelante sobre lo que está sucediendo: algunas conversiones implicit transparentes de las implicit me debería sorprender algunas veces ahora (¿¿ Option de Iterable para alguien?) Y este uso aún nos permite aprovechar El poder del s implicit .


Creo que la forma más "explícita" 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 los implicit totalmente transparente desde el tipo A hasta el tipo B es correcto cuando siempre se puede ver un objeto del tipo A que se puede usar siempre que se necesita un objeto del tipo B Por ejemplo, la conversión implícita de una String a un RandomAccessSeq[Char] siempre tiene sentido: una 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 todas las String .

Por otro lado, las conversiones más explícitas se deben usar cuando un objeto de tipo A veces se puede usar como un objeto de tipo B En su ejemplo, una llamada a foo("bar") no tiene sentido y arroja 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) se ve claramente mal, 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 RichString envoltorio RichString ( String s puede verse como Int s, pero no todo el tiempo ).


Cuando realiza una conversión implícita de X a Y (como la conversión de String a Date anterior), básicamente dice que, si hubiera tenido el control total sobre la escritura de X en primer lugar, habría hecho X implementado o sería un 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).