Podría / debería una conversión implícita de T a Opción [T] se añadirá / creada en Scala?
-
20-09-2019 - |
Pregunta
¿Es esta una oportunidad para hacer las cosas un poco más eficiente (para el prorammer): Encuentro se pone un poco molesto tener que envolver las cosas en Some
, por ejemplo, Some(5)
. ¿Qué pasa con algo como esto:
implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
Solución
Se podría perder algo de seguridad de tipos y posiblemente causar confusión. Por ejemplo:
val iThinkThisIsAList = 2
for (i <- iThinkThisIsAList) yield { i + 1 }
I (por cualquier razón) pensaba que tenía una lista, y no quedar atrapados por el compilador cuando se repiten a lo largo ya que se convirtió-auto a una opción [Int].
Debería añadir que creo que esto es una gran implícita haber importado de manera explícita, simplemente probablemente no es un valor predeterminado global.
Otros consejos
Tenga en cuenta que usted podría utilizar el patrón implícita la explícita lo que evitaría la confusión y mantener el código conciso al mismo tiempo.
Lo que quiero decir con implícita es explícita en lugar de tener una conversión directa de T
a Option[T]
usted podría tener una conversión a un objeto envolvente que proporciona los medios para hacer la conversión de T
a Option[T]
.
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)
... que podría encontrar un nombre mejor para él que Optionable
, pero ahora se puede escribir código como:
val x: String = "foo"
x.toOption // Some("foo")
val y: String = null
x.toOption // None
Creo que de esta manera es totalmente transparente y ayuda en la comprensión del código escrito. - eliminando todos los controles relacionados nula de una manera agradable
Tenga en cuenta el T <: AnyRef
-. Sólo debe hacer esta conversión implícita de tipos que permiten a los valores null
, que por definición son los tipos de referencia
Las directrices generales para las conversiones implícitas son como sigue:
- Cuando es necesario agregar miembros a un tipo (a la "clases abiertas", también conocido como el patrón de "Pimp mi biblioteca"), convertir a un nuevo tipo que se extiende
AnyRef
y que sólo se define el miembros que necesitan. - Cuando se necesita una jerarquía de herencia "correcta". Por lo tanto, usted tiene algún tipo
A
que debe tenerB
subclase, pero no lo hizo por alguna razón. En ese caso, se puede definir una conversión implícita deA
aB
.
Estos son los sólo casos en que sea apropiado para definir una conversión implícita. Cualquier otro tipo de conversión se encuentra con problemas de seguridad y corrección del tipo de prisa.
Realmente no tiene ningún sentido para T
para extender Option[T]
, y, obviamente, el propósito de la conversión no es simplemente la adición de los miembros. Por lo tanto, tal conversión no sería aconsejable.
Parece que esto podría ser confuso para otros desarrolladores, a medida que leen el código.
En general, parece, implicit
trabaja para ayudar molde de un objeto a otro, para cortar código de fundición confuso que puede estorbar código, pero, si tengo alguna variable y de alguna manera se convierte en un Some
entonces que parecería ser molestos .
Es posible que desee poner un poco de código que se está utilizando, para ver lo confuso que sería.
También puede tratar de sobrecargar el método:
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
}
Esto se ve muy bueno para mí, si no puede trabajar para una camiseta primitiva (que no puede ser nulo). Supongo que un no especializados genéricos primitivas siempre se pone en caja, por lo que probablemente está bien.