Domanda

Mi chiedevo se le conversioni trasparenti implicite siano davvero una buona idea e se potrebbe effettivamente essere meglio usare implicitamente più, ehm, esplicitamente . Ad esempio, supponiamo di avere un metodo che accetta una Date come parametro e di avere una conversione implicita che trasforma una String in una Date :

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

private def foo(d: Date)

Quindi ovviamente posso chiamarlo con una conversione implicita trasparente:

foo("20090910")

Sarebbe meglio rendere più esplicito il fatto che sto convertendo la stringa in una data?

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

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

Quindi l'utilizzo appare più simile a:

foo("20090910".toDate)

Il vantaggio di questo è che è più chiaro in seguito ciò che sta accadendo: sono stato scoperto alcune volte da conversioni implicite trasparenti che dovrei conoscere (opzione a Iterable chiunque?) e questo utilizzo ci consente ancora di sfruttare il potere di implicito s.

È stato utile?

Soluzione

Credo che quanto più "esplicito" sia il modo di fare conversioni implicite è molto meglio in termini di leggibilità rispetto a quello completamente trasparente, almeno in questo esempio.

Secondo me, usare implicito in modo completamente trasparente dal tipo A al tipo B è OK quando puoi sempre visualizza un oggetto di tipo A come utilizzabile ogni volta che è necessario un oggetto di tipo B . Ad esempio, la conversione implicita di una String in una RandomAccessSeq [Char] ha sempre un senso: una String può sempre essere, concettualmente, vista come una sequenza di caratteri (in C, una stringa è solo una sequenza di caratteri, per esempio). Una chiamata a x.foreach (println) ha senso per all String s.

D'altra parte, le conversioni più esplicite dovrebbero essere usate quando un oggetto di tipo A può a volte essere usato come oggetto di tipo B . Nel tuo esempio, una chiamata a foo (" bar ") non ha senso e genera un errore. Poiché Scala non ha verificato le eccezioni, una chiamata a foo (s.toDate) indica chiaramente che potrebbe essere generata un'eccezione ( s potrebbe non essere una data valida). Inoltre, foo (" bar " .toDate) sembra chiaramente sbagliato, mentre devi consultare la documentazione per capire perché foo (" bar ") potrebbe essere sbagliato. Un esempio di ciò nella libreria standard di Scala sono le conversioni da String a Int , tramite il metodo da aInt del RichString wrapper ( String s può essere visto come Int s, ma non sempre ).

Altri suggerimenti

Quando effettui una conversione implicita da X a Y (come la conversione da String a Date sopra), stai essenzialmente dicendo che, se avessi avuto il pieno controllo sulla scrittura di X in primo luogo, avresti fatto implementare X o essere una sottoclasse di Y.

Se ha senso per X implementare Y, allora aggiungi la conversione. In caso contrario, forse non è appropriato. Ad esempio, ha senso per String implementare RandomAccessSeq [Char], ma forse non ha senso per String implementare Date (anche se String che implementa StringDate sembra a posto).

(Sono un po 'in ritardo e Flaviu ha una risposta eccellente, ma volevo aggiungere un commento su come penso alle implicazioni.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top