我有一个框架,它定义了一个类型类,其中大多数实例都具有特定的隐式值:
import scala.reflect.runtime.universe.TypeTag
sealed trait Source
// many classes with implicit TypeTag
case class SourceA[T]()(implicit val ev: TypeTag[T]) extends Source
case class SourceB[T]()(implicit val ev: TypeTag[T]) extends Source
case class SourceC[T]()(implicit val ev: TypeTag[T]) extends Source
// a few classes without TypeTag
case class EmptySource() extends Source
在我的应用程序中,我想使用简单的代码访问上面示例中的ev
。以下是我的想法:
def retrieveTypeTagFromSource(source: Source): Option[TypeTag[_]] = source match {
case s: SourceA[_] => Some(s.ev)
case s: SourceB[_] => Some(s.ev)
case s: SourceC[_] => Some(s.ev)
// many more nearly identical lines
// then handling the remaining classes
case s: EmptySource => None
}
有很多重复,并不理想。我想消除它们,而不仅仅是将重复转移到框架侧(例如,为每个适用的案例类添加HasTypeTag
特征(。当模式匹配时,我尝试使用以下行:
case s: {val ev: TypeTag[Any]} => Some(s.ev)
但Scala警告a pattern match on a refinement type is unchecked
,所以我不知道这是否真的有效。
添加类似HasTypeTag
的内容不必重复,只需具有两个不同的traits
,并根据需要扩展TaggedSource
或UntaggedSource
即可。
import scala.reflect.runtime.universe.TypeTag
sealed trait Source
{
def ott: Option[TypeTag[_]]
}
abstract class TaggedSource[T]()(implicit val tt: TypeTag[T]) extends Source {
def ott = Some(tt)
}
trait UntaggedSource extends Source {
def ott = None
}
// many classes with implicit TypeTag
case class SourceA[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
case class SourceB[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
case class SourceC[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
// a few classes without TypeTag
case class EmptySource() extends UntaggedSource
def retrieveTypeTagFromSource(source: Source): Option[TypeTag[_]] =
source.ott