2010-11-30 15 views
6

Quiero crear un hashmap para almacenar los nombres de los parámetros y sus valores. Sin embargo, los parámetros son de diferentes tipos. Podría usar HashMap [String, Any], pero no sabría qué tipos son más adelante. ¿De todos modos puedo recuperar la información del tipo? ¿O hay alguna forma mejor de almacenar pares?scala reflection

+0

posible duplicado de [¿Cómo puedo evitar el borrado de tipo en Scala? O bien, ¿por qué no puedo obtener el parámetro de tipo de mis colecciones?] (Http://stackoverflow.com/questions/1094173/how-do-i-get-around-type-erasure-on-scala-or-why -cant-i-get-the-type-parameter) –

+0

¿Alguna de estas respuestas le resultó útil? De lo contrario, ¿tiene algún comentario que nos ayude a enfocar mejor sus necesidades? –

+0

bueno, ninguno de ellos realmente resolvió mi problema. Algunas personas me dijeron (fuera de línea) que no hay una solución elegante. Cambié mi diseño más tarde para evitar ese problema ... – user398384

Respuesta

5

¿Desea acceder a la información de tipo estático o a la información de tipo dinámico? Si buscas lo primero, puedes usar claves mecanografiadas. Algo a lo largo de estas líneas debería funcionar:

final class Key[T] 

object Registry { 
    private var backingMap: Map[Key[_], _] = Map.empty 

    def put[T](k: Key[T], v: T) = backingMap += (k -> v) 

    def get[T](k: Key[T]): Option[T] = backingMap get k map (_.asInstanceOf[T]) 
} 

scala> val strKey = new Key[String] 
strKey: Key[String] = [email protected] 

scala> val intKey = new Key[Int] 
intKey: Key[Int] = [email protected] 

scala> Registry.put(strKey, "asdf") 

scala> Registry.get(strKey) 
res0: Option[String] = Some(asdf) 

scala> Registry.put(intKey, "asdf") 
<console>:10: error: type mismatch; 
found : Key[Int] 
required: Key[Any] 
     Registry.put(intKey, "asdf") 

alternativa, puede utilizar las teclas de untyped y almacenar la información de tipo en el mapa usando los manifiestos (como Daniel suggested):

class Registry[K] { 
    import scala.reflect.Manifest 

    private var _map= Map.empty[K,(Manifest[_], Any)] 

    def put[T](key: K, item: T)(implicit m: Manifest[T]) { 
     _map += (key -> (m, item)) 
    } 

    def get[T](key:K)(implicit m : Manifest[T]): Option[T] = { 
     for ((om, v) <- _map get key if om <:< m) 
     yield v.asInstanceOf[T] 
    } 
} 

Este último enfoque tiene la ventaja de que puede usar cualquier cosa como clave, y no tiene que pasar los objetos de la clave mecanografiada original. Sin embargo, tiene el inconveniente de que debe especificar el tipo de valor cuando llama al método get. Si especifica el tipo incorrecto obtendrá None como si la clave no estuviera en absoluto en el Registro, mientras que con las claves mecanografiadas está garantizado que obtendrá cualquier valor asociado con una clave.

1

Si no tiene demasiados valores, puede considerar el uso de HList de Pares o construcciones similares.

3

Consulte this, que implementa exactamente lo que usted solicita.

+0

¡Agradable! Simplifiqué un poco su implementación en mi respuesta e intenté explicar las diferencias entre el enfoque de clave mecanografiada y el enfoque de manifiesto almacenado. –