我有自定义类型Value
:
trait Value
object Value {
case class BooleanValue(record: Boolean) extends Value
case class LongValue(record: Long) extends Value
}
一个知道如何获得Value
的特征,称为GetsValue
,给定一些输入类型T
:
sealed trait GetsValue[T] { def apply(record: T): Option[Value] }
object GetsValue {
trait GetsBooleanValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.BooleanValue] }
trait GetsLongValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.LongValue] }
}
请注意,GetsValue是密封的,因此用户只会展开GetsValue.GetsBooleanValue
或GetsValue.GetsLongValue
。
trait Extractor[T] {
def title: String
def getsValue: GetsValue[T]
def relatedValue[U]: U = ??? // question below
}
我想要实现的目标如下:
如果getsValue
是GetsValue.GetsBooleanValue[_]
,则返回String
,文字为“boo!” (即U
的类型为String
)。
如果getsValue
是GetsValue.GetsLongValue[_]
,则返回值为1.1的Double
(即,U
的类型为Double
)。
另请注意,我不想匹配getsValue
的{{1}}类型。无论类型T
是什么,我都希望匹配。
如果有意义,我想使用类型class / implicits。 使用T
不是我的选择。
答案 0 :(得分:2)
也许这样的事情会起作用:
首先,修改GetsValue
以添加指定返回类型的类型参数:
sealed trait GetsValue[T, V <: Value] { def apply(record: T): Option[V] }
object GetsValue {
trait GetsBooleanValue[T] extends GetsValue[T, Value.BooleanValue] { }
trait GetsLongValue[T] extends GetsValue[T, Value.LongValue] { }
}
然后使用特征将类型V
与值U
相关联:
trait RelatedValue[V <: Value, U] {
def get: U
}
该特质的一些隐含价值:
object Extractor {
implicit val boolRV = new RelatedValue[Value.BooleanValue, String] { def get = "boo!" }
implicit val longRV = new RelatedValue[Value.LongValue, Double] { def get = 1.1 }
}
然后你的提取器特征可以是:
trait Extractor[T] {
type V <: Value
type U
def title: String
def getsValue: GetsValue[T, V]
def relatedValue(implicit rv: RelatedValue[V, U]): U = rv.get
}
示例实现:
object Example extends Extractor[String] {
type V = Value.BooleanValue
type U = String
def title = "Example"
def getsValue = new GetsValue.GetsBooleanValue[String] {
def apply(s: String) = None
}
}
import Extractor._
println(Example.relatedValue)
打印“嘘!”