如何实现具有混合但受限类型的值的键,值对的集合

时间:2018-08-20 16:58:08

标签: scala typeclass generic-collections

这里的一个用例是想象一个配置对象,它是键-值对的集合。

我想创建一个表示此键,值对集合的类型。而且我也想让值具有不同的类型。此外,尽管这些值是不同类型的,但我还是希望将这些键,值对保留在一个集合中。但是我根本不想允许任何类型的值。最后,我希望能够恢复给定键的值。 (奖励积分,我想确保键是唯一的)

类似的东西:

trait Property
case class SProperty(name: String, value:String) extends Property
case class DProperty(name: String, value:Double) extends Property
case class IProperty(name: String, value:Int) extends Property

case class Properties(props: List[Property]) {
  def getValueByName(name: String) = {
    props.find(p => p.name == name).map(p => p.value)
  } 
}

这行得通,但是它创建了一个难看的API。例如:

val properties = Properties(
  List(
    Property("some name", "some value"),
    Property("another name", "another value")
  )
)

如果我的测试可以检查:

properties.getValueByName("some name").getOrElse(None) shouldBe "some value"

测试将失败,并显示

SProperty("some value") is not equal to "some value"

我考虑使用无形的HList,但是这将允许Properties接受任何类型。我只希望集合中的Property类型,并且我希望其中的值限于类型String | Double | Int

是否有更好的方法来定义键值对的集合,该键值对允许一组特定的值类型,并且可以为我提供.get方法?

是否有更好的方法来定义我的getValueByName方法,使其返回基础值而不是包装值?

一种方法是这样编写吸气剂:

def getValueByName[T](name: String): Option[Any] = {
  Properties.find(p => p.name == name).map {
    case Property(_, SProperty(v)) => Some(v)
    case Property(_, DProperty(v)) => Some(v)
    case Property(_, IProperty(v)) => Some(v)
    case _ => None
}

}

但这在修改代码以添加允许属性值的新类型的地方开始很多。返回Option[Any]似乎是错误的。要使用吸气剂,您需要提前知道值的类型。那可能很好,但是可能很麻烦。

我也无法找到使用类型类的可接受方法,但是我承认我对编写类型类没有很深的经验。

0 个答案:

没有答案