2009-09-10 14 views
23

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

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

private def foo(d: Date) 

entonces, evidentemente, que pueda llamar esto con una conversión transparente implicit:

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) 

Con esto, el uso se parece más a:

foo("20090910".toDate) 

La ventaja de esto es que es más claro más adelante lo que está sucediendo - Me han pillado varias veces por implicit transparente conversiones que debería saber (Option a Iterable ¿alguien?) y este uso todavía nos permite aprovechar la potencia de implicit s.

Respuesta

43

Creo que la forma más "explícita" de realizar 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 implicit s totalmente transparente desde el tipo A para escribir B está bien cuando se puede siempre ver un objeto de tipo A como ser capaz de ser utilizado en cualquier momento y es necesaria objeto de tipo B. Por ejemplo, la conversión implícita de String a RandomAccessSeq[Char] siempre tiene sentido: una String siempre puede, conceptualmente, verse 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 todoString s.

Por otro lado, las conversiones más explícito, deben utilizarse cuando un objeto de tipo A puede veces ser utilizado como un objeto de tipo B. En su ejemplo, una llamada al foo("bar") no tiene sentido y arroja un error. Como Scala no ha marcado excepciones, una llamada al foo(s.toDate) indica claramente que puede haber una excepción lanzada (s podría no ser una fecha válida). Además, foo("bar".toDate) claramente se ve mal, mientras que necesita consultar la documentación para ver por qué foo("bar") podría estar equivocado. Un ejemplo de esto en la biblioteca estándar Scala es conversiones de String s a Int s, a través del método de la RichString envoltura toInt (String s pueden ser vistos como Int s, pero no todo el tiempo).

13

Cuando realiza una conversión implícita de X a Y (como la conversión de Cadena a Fecha anterior), básicamente está diciendo que, si hubiera tenido el control total de escribir X en primer lugar, habría hecho X implementar o ser una subclase de Y.

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

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

Cuestiones relacionadas