Könnte / sollte eine implizite Konvertierung von T Option [T] in Scala hinzugefügt / erstellt werden?
-
20-09-2019 - |
Frage
Ist dies eine Gelegenheit, die Dinge ein wenig effizienter zu machen (für die prorammer): Ich finde es wird ein wenig ermüdend Dinge in Some
wickeln, z.B. Some(5)
. Was ist so etwas wie folgt aus:
implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
Lösung
Sie würden eine Art Sicherheit verlieren und möglicherweise Ursache Verwirrung. Zum Beispiel:
val iThinkThisIsAList = 2
for (i <- iThinkThisIsAList) yield { i + 1 }
I (aus irgendeinem Grund) dachte, dass ich eine Liste hatte, und es hat nicht durch den Compiler erwischt, wenn ich über sie wiederholt, weil es zu einer Option Auto-umgewandelt wurde [Int].
Ich sollte hinzufügen, dass ich denke, das ist eine große implizit explizit importiert zu haben, nur wahrscheinlich kein globaler Standard.
Andere Tipps
Beachten Sie, dass Sie die explizit implizit Muster verwenden könnte, die Verwirrung vermeiden würde und Code kurz und bündig zur gleichen Zeit halten.
Was ich damit meine ausdrückliche implizite ist, anstatt eine direkte Umwandlung von T
müssen Option[T]
Sie eine Umwandlung in ein Wrapper-Objekt haben könnte, die die Mittel bereitstellt, um die Umwandlung von T
zu Option[T]
zu tun.
class Optionable[T <: AnyRef](value: T) {
def toOption: Option[T] = if ( value == null ) None else Some(value)
}
implicit def anyRefToOptionable[T <: AnyRef](value: T) = new Optionable(value)
... Ich könnte einen besseren Namen für sie als Optionable
finden, aber jetzt können Sie Code schreiben, wie:
val x: String = "foo"
x.toOption // Some("foo")
val y: String = null
x.toOption // None
Ich glaube, dass auf diese Weise vollkommen transparent ist und hilft beim Verständnis der geschriebenen Code -. Alle Prüfungen für null auf einer netten Art zu beseitigen
Beachten Sie die T <: AnyRef
-. Sie sollten nur bei den Typen diese implizite Konvertierung tun, die null
Werte erlauben, die definitionsgemäß Referenztypen
Die allgemeinen Richtlinien für die impliziten Konvertierungen sind wie folgt:
- Wenn Sie Mitglieder zu einer Art hinzufügen müssen (a la „offene Klassen“, auch bekannt als die „meine Bibliothek pimp“ -Muster), convert zu einem neuen Typ den sich
AnyRef
und die definiert, nur die Mitglieder, die Sie benötigen. - Wenn Sie zu „korrigieren“ einer Vererbungshierarchie benötigen. So Sie irgendeine Art
A
haben, die haben sollte UnterklasseB
, aber tat aus irgendeinem Grund nicht. In diesem Fall können Sie eine implizite Konvertierung vonA
zuB
definieren.
Die nur Fälle, in denen es angemessen ist eine implizite Konvertierung zu definieren. Jede andere Umwandlung läuft in Typsicherheit und Korrektheit Probleme in Eile.
Es macht wirklich keinen Sinn für T
Option[T]
zu verlängern, und offensichtlich den Zweck der Umwandlung ist nicht einfach die Zugabe von Mitgliedern. Somit ist eine solche Umwandlung würde nicht ratsam sein.
Es scheint, dass diese an andere Entwickler verwirrend sein könnte, da sie den Code zu lesen.
Generell scheint es, funktioniert implicit
zu Hilfe Besetzung von einem Objekt zum anderen, verwirrenden auszuschneiden Code Gießen das kann Krempel-Code, aber, wenn ich eine Variable haben, und es wird irgendwie ein Some
dann würde das scheint lästig zu sein .
Sie können einige Code setzen zeigt es verwendet wird, um zu sehen, wie verwirrend es sein würde.
Sie können auch versuchen, das Verfahren zu überlasten:
def having(key:String) = having(key, None)
def having(key:String, default:String) = having(key, Some(default))
def having(key: String, default: Option[String]=Option.empty) : Create = {
keys += ( (key, default) )
this
}
Das sieht gut aus für mich, außer es möglicherweise nicht für ein primitiven T (die nicht null sein kann). Ich denke, ein nicht spezialisierten generic immer boxed Primitiven wird, so wahrscheinlich es ist in Ordnung.