【问题标题】:Is there any way to get Key/Value type from a map in Scala?有没有办法从 Scala 的地图中获取键/值类型?
【发布时间】:2016-04-10 17:12:14
【问题描述】:

在 C++ 中,我们可以从定义的映射中获取 abstract 键/值类型(key_typevalue_typehttp://en.cppreference.com/w/cpp/container/map)。当我需要稍后更改地图类型时,这非常方便,因为依赖类型会相应更改。

在 Scala 中,我也在寻找这样的功能。比如我定义了一个map类型:

type MapTy : mutable.Map[Long, Int]

我希望返回一个地图条目(其类型为Long->Int)。返回类型取决于MapTy,最好在函数签名中明确指定,写成MapTy::key_type->MapTy::value_type。因此,稍后我将MapTy 更改为

type MapTy : mutable.Map[Int, Int]

条目类型也会同时更改为Int->Int

在 Scala 中可以吗?

【问题讨论】:

  • 您能编写示例代码来演示您的预期用例吗?即使它没有编译。

标签: scala types


【解决方案1】:

在 Scala 中完全可以用类型成员和类型细化来做这种事情:

scala> case class WrappedMap[K, V](underlying: Map[K, V]) { type E = (K, V) }
defined class WrappedMap

scala> type MapTy = WrappedMap[Long, Int]
defined type alias MapTy

scala> val entry: MapTy#E = 1L -> 0
entry: (Long, Int) = (1,0)

scala> val entry: MapTy#E = 1L -> "foo"
<console>:14: error: type mismatch;
 found   : String("foo")
 required: Int
       val entry: MapTy#E = 1L -> "foo"
                                  ^

或者:

def entries(m: MapTy): List[MapTy#E] = m.underlying.toList

val myEntries: List[MapTy#E] = entries(WrappedMap(Map(1L -> 0)))

标准集合库大部分不包含表示元素类型的类型成员,部分原因是通用使用类型参数更适合惯用的 Scala 开发实践,但在某些情况下类型成员很有用,如果你真的想近似你在 C++ 中描述的内容,这可能就是其中之一。

【讨论】:

    【解决方案2】:

    在 Scala 中,泛型类型在擦除时会丢失,因此在运行时是不可能的。有人可能会展示如何做到这一点,在此之前,这里有一个解决方法:

    type Key = Int
    type Value = Long
    type Map = mutable.Map[Key, Value]
    

    另外,this 可能会有所帮助。

    【讨论】:

    • 抱歉,但我不清楚这种情况与哪种类型的擦除有关——你能在这部分展开吗?
    • 我必须说我不是自我声明类型的专家,但我认为它们的工作方式与任何其他类型一样。所以在擦除之后,在运行时,映射的类型只是mutable.Map,所有关于键和值类型的信息都丢失了。这就是为什么您要问的内容在运行时是不可能的。在编译时可能有可能,但我不知道有什么方法可以做到这一点(但 scala 每天都让我感到惊讶,所以不要认为这是不可能的)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2021-02-28
    相关资源
    最近更新 更多