Pergunta

Eu estive pensando se transparente conversões implicit são realmente uma boa idéia e se ele pode realmente ser melhor para implícitos uso mais, hum, explicitamente . Por exemplo, suponha que eu tenho um método que aceita uma Date como um parâmetro e eu tenho uma conversão implícita que transforma um String em um Date:

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

private def foo(d: Date)

Então, obviamente, eu posso chamar isso com uma conversão implicit transparente:

foo("20090910")

Seria melhor para tornar o fato de que eu estou convertendo a string em uma data mais explícito?

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

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

Então os olhares de uso mais como:

foo("20090910".toDate)

A vantagem desta é que é mais clara, mais tarde, o que está acontecendo - Fui apanhado algumas vezes agora por conversões implicit transparentes que eu deveria saber (Option para Iterable alguém?) E este uso ainda nos permite tirar proveito do poder de implicits.

Foi útil?

Solução

Eu acredito que a maneira mais "explícita" de fazer conversões implícitas é muito melhor em termos de legibilidade do que o totalmente transparente, pelo menos neste exemplo.

Na minha opinião, usando implicits totalmente transparente do tipo A o tipo B é OK quando você pode sempre ver um objeto do tipo A como sendo capaz de ser usado sempre e é necessária objeto do tipo B . Por exemplo, a conversão implícita de um String a um RandomAccessSeq[Char] sempre faz sentido - um String sempre pode, conceitualmente, ser visto como uma sequência de caracteres (em C, uma string é apenas uma sequência de caracteres, por exemplo). Uma chamada para x.foreach(println) faz sentido para todas Strings.

Por outro lado, as conversões mais explícitas deve ser usado quando um objeto do tipo A podem às vezes ser usado como um objeto do tipo B. No seu exemplo, uma chamada para foo("bar") não faz sentido e gera um erro. Como Scala não tem exceções verificadas, uma chamada para foo(s.toDate) claramente sinais de que pode haver uma exceção lançada (s pode não ser uma data válida). Além disso, foo("bar".toDate) parece claramente errada, enquanto você precisa consultar a documentação para ver porque foo("bar") pode estar errado. Um exemplo disto na biblioteca padrão Scala é conversões de Strings para Ints, através do método toInt da embalagem RichString (Strings pode ser visto como Ints, mas não o tempo todo ).

Outras dicas

Quando você faz uma conversão implícita de X para Y (como a conversão de String para Data acima), você está dizendo essencialmente que, se você tinha o controle total sobre escrever X em primeiro lugar, você teria feito X implementar ou ser uma subclasse de Y.

Se faz sentido para X para implementar Y, em seguida, adicione a conversão. Se isso não acontecer, então talvez não seja apropriado. Por exemplo, não faz sentido para String para implementar RandomAccessSeq [Char], mas talvez isso não faz sentido para String para implementar Data (embora Cordas implementação StringDate parece muito bem).

(eu sou um pouco tarde, e Flaviu tem uma excelente resposta, mas eu queria adicionar um comentário sobre a forma como eu penso sobre implícitos).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top