2009-11-17 8 views

Respuesta

30

Perderá algún tipo de seguridad y posiblemente cause 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] .

Debo añadir que creo que esto es un gran implícito para haber importado explícitamente, probablemente no sea un valor predeterminado global.

+0

Al menos en IntelliJ IDEA puedo ver cuando algo se convierte automáticamente (por defecto está subrayado). Pero tal vez debería haber una forma de especificar que una conversión implícita solo debería ocurrir al pasar el valor a un método, no cuando se llama a un método. – herman

1

Parecería 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 molesto.

Es posible que desee poner un código que muestre su uso, para ver qué tan confuso sería.

+1

que consigo su deriva .. Sin embargo, el punto de Opción [T] es que puede contener un valor o una Ninguno, por lo que parece intuitivo que si un método toma una variable de tipo Opción [T], debería poder pasar una T a él. ¿Puedes pensar en un ejemplo en el que puedas tener alguna confusión, p. una variable convirtiéndose en algo inadvertidamente? –

-2

Eso se ve bien para mí, excepto que puede no funcionar para una T primitiva (que no puede ser nula). Supongo que un genérico no especializado siempre obtiene primitivos en caja, por lo que probablemente esté bien.

25

Tenga en cuenta que podría utilizar el patrón explicit implicit que evitaría la confusión y mantendría el código al mismo tiempo.

Lo que quiero decir es explícita implí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 de el código escrito - eliminando todos los cheques por nulo de una manera agradable.

Tenga en cuenta que T <: AnyRef solo debe realizar esta conversión implícita para los tipos que permiten los valores null, que por definición son tipos de referencia.

+0

Hola Flaviu, sugerencia interesante. Me gusta en general, aunque creo que no empeora mi problema, ahora, en lugar de escribir Some(), tengo que escribir toOption ... pero tiene la ventaja de trabajar con null. –

+6

'La opción (x)' (en lugar de 'Some (x)') también funciona con null. – schmmd

+2

@ flaviu-cipcigan, hace lo mismo pero más corto - clase implícita IntWithTimes [T] (x: T) { def toOption: Opción [T] = if (x! = Null) Opción (x) else Ninguno } – Maxim

11

Las directrices generales para las conversiones implícitas son las siguientes:

  • Cuando es necesario agregar miembros a un tipo (a la "clases abiertas", también conocido como el "proxeneta mi biblioteca" patrón), convertir a una nuevo tipo que se extiende AnyRef y que solo define los miembros que necesita.
  • Cuando necesita "corregir" una jerarquía de herencia.Por lo tanto, tiene algún tipo A que debería tener subclasificado B, pero no lo hizo por alguna razón. En ese caso, puede definir una conversión implícita de A a B.

Estas son las sólo casos en que sea apropiado para definir una conversión implícita. Cualquier otra conversión se encuentra con problemas de seguridad y corrección de tipo a toda prisa.

Realmente no tiene ningún sentido para T extender , y obviamente el propósito de la conversión no es simplemente la adición de miembros. Por lo tanto, tal conversión sería desaconsejable.

0

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 
} 
Cuestiones relacionadas