代码之家  ›  专栏  ›  技术社区  ›  Troy Daniels

从Scala映射中获取具有通配符键类型的值

  •  0
  • Troy Daniels  · 技术社区  · 5 年前

    我有一个 Map

    trait Foo { }
    
    class FooImpl extends Foo {}
    class Sample
    {
        val m: Map[_ <: Foo, String] =  Map()
        val foo: Foo = new FooImpl
    
        // This line fails to compile
        m(foo)
    
        val m2: Map[Foo, String] =  Map()
        // This line compiles fine (but will throw at runtime)
        m2(foo)
    }
    

    我使用的是scala 2.12,通配符版本无法编译:

    [info] Compiling 1 Scala source to /test/scala/target/scala-2.12/classes ...
    [error] /test/scala/src/main/scala/Test.scala:10:7: type mismatch;
    [error]  found   : Sample.this.foo.type (with underlying type Foo)
    [error]  required: _$1
    [error]     m(foo)
    [error]       ^
    [error] one error found
    

    有没有可能从第一张地图上得到具体的数值( m m.filter({(k,v) => k.equals(foo)}) ? 在爪哇,我可以做到 m.get(foo) 而且Scala似乎不太可能强迫我比Java更详细、更不清晰。

    . 我知道 m2(foo) 将在运行时抛出。在实际情况下,地图包含 foo . 我的问题是编译错误,而不是运行时错误。

    0 回复  |  直到 5 年前
        1
  •  0
  •   Volty De Qua    5 年前

    您需要映射的较低类型边界(>:而不是<:)

    trait Foo
    val foo = new Foo {}
    val m: Map[_ >: Foo, String] = Map(foo -> "hi")
    m(foo) // String = hi
    m.get(new Foo {}) // Option[String] = None
    

    在一个评论问题之后:假设我们有一个上界,并且想把它转换成下界

    val n: Map[_ <: Foo, String] = Map(foo -> "hi")
    n(foo) // does not compile
    def upper2lower(x: Map[_ <: Foo, String]): Map[_ >: Foo, String] = Map(x.toSeq:_*)
    upper2lower(n)(foo) // String = hi