这里的一个用例是想象一个配置对象,它是一个键值对的集合。
我想创建一个类型来表示这个键、值对的集合。我也希望这些价值观是多种多样的。此外,我希望将这些键和值对保存在一个集合中,尽管这些值属于不同的类型。但我根本不想让这些值按任何类型排列。最后,我希望能够恢复给定密钥的值。(加分,我想确保钥匙是唯一的)
类似于:
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
方法以返回基础值而不是包装值?
一种方法是这样写getter:
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]
似乎错了。要使用getter,您需要提前知道值的类型。那也许不错,但可能会很麻烦。
我也找不到一个可以接受的使用类型类的方法,但是我承认我对编写类型类没有很深的经验。