Scala implizite Nutzung Entscheidungen
Frage
Ich habe mich gefragt, ob transparent implicit
Umwandlungen sind wirklich so eine gute Idee ist und ob es vielleicht sogar besser sein implicits mehr zu verwenden, um, explizit . Angenommen, ich habe eine Methode, die ein Date
als Parameter akzeptiert, und ich habe eine implizite Konvertierung, die eine String
in eine Date
verwandelt:
implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
private def foo(d: Date)
Dann natürlich kann ich nenne dies mit einer transparenten implicit
Umwandlung:
foo("20090910")
Wäre es besser, die Tatsache zu machen, dass ich die Zeichenfolge in ein Datum an Umwandlung expliziten?
class DateString(val s: String) {
def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
}
implicit def str2datestr(s: String) : DateString = new DateString(s)
So wird die Nutzung sieht eher aus wie:
foo("20090910".toDate)
Der Vorteil hierbei ist, dass es klarer später, was passiert - ich habe ein paar Mal jetzt durch transparente implicit
Konvertierungen ertappt ich wissen sollte und diese Nutzung noch erlaubt uns (Option
jemand Iterable
?) nutzen Sie die Kraft des implicit
s.
Lösung
Ich glaube, die mehr „explicit“ Art und Weise implizite Konvertierungen zu tun.
Meiner Meinung nach, implicit
geben A
s vollständig transparent vom Typ B
mit OK ist, wenn Sie können immer ein Objekt vom Typ A
anzuzeigen in der Lage, verwendet werden, wann immer und Objekt vom Typ B
benötigt wird . Zum Beispiel macht die implizite Umwandlung eines String
zu einem RandomAccessSeq[Char]
immer Sinne - ein String
immer kann konzeptionell als eine Folge von Zeichen betrachtet wird (in C, ist eine Zeichenfolge nur eine Folge von Zeichen, zum Beispiel). Ein Aufruf von x.foreach(println)
macht Sinn für alle String
s.
Auf der anderen Seite, die mehr expliziten Konvertierungen sollten verwendet werden, wenn ein Objekt vom Typ A
kann manchmal als ein Objekt vom Typ B
verwendet werden. In Ihrem Beispiel wird ein Aufruf an foo("bar")
nicht Sinn und wirft einen Fehler. Wie Scala nicht geprüfte Ausnahmen hat, ein Anruf eindeutig foo(s.toDate)
signalisiert, dass es möglicherweise eine Ausnahme ausgelöst werden (s
vielleicht kein gültiges Datum sein). Auch sieht foo("bar".toDate)
eindeutig falsch, während Sie Dokumentation konsultieren müssen, um zu sehen, warum foo("bar")
könnte falsch sein. Ein Beispiel hierfür in der Scala-Standardbibliothek ist Konvertierungen von String
s zu Int
s über die toInt
Methode des RichString
Wrapper (String
s als Int
s zu sehen, aber nicht die ganze Zeit ).
Andere Tipps
Wenn Sie eine implizite Konvertierung von X nach Y machen (wie die Umwandlung von String zu Datum oben), sind Sie im Wesentlichen das zu sagen, Sie hatte die volle Kontrolle über Schrift X in erster Linie hätten, würden Sie gemacht haben X zu implementieren oder sein eine Unterklasse von Y.
Wenn es Sinn macht, für X-Y zu implementieren, dann die Konvertierung hinzuzufügen. Wenn dies nicht der Fall, dann ist es vielleicht nicht angemessen. Zum Beispiel macht es Sinn, für String RandomAccessSeq [Char], zu implementieren, aber vielleicht macht es keinen Sinn macht für String Datum zu implementieren (obwohl String Umsetzung StringDate scheint in Ordnung).
(Ich bin ein wenig zu spät, und Flaviu hat eine ausgezeichnete Antwort, aber ich wollte einen Kommentar hinzufügen, wie ich denke, über implicits.)