Scala Seq – 仅接受相同子类型的元素
发布时间:2020-12-16 18:37:11 所属栏目:安全 来源:网络整理
导读:假设我有一个类似以下的类型层次结构: trait Colorcase class Red(r: String) extends Colorcase class Green(g: String) extends Color 是否有可能创建一个接受Seq [Color]的方法,该Seq [Color]包含全部为Red的元素,或者全部为Green,但不是两者都包含? 例
假设我有一个类似以下的类型层次结构:
trait Color case class Red(r: String) extends Color case class Green(g: String) extends Color 是否有可能创建一个接受Seq [Color]的方法,该Seq [Color]包含全部为Red的元素,或者全部为Green,但不是两者都包含? 例如,在以下代码中: def process[T](colors: Seq[T]) = colors.size process(Seq(Red("a"),Green("g"))) [T]应该是什么,以便上面不进行类型检查? 编辑 最初的问题如下:我正在尝试为嵌套查询设计JSON API.我想出了以下设计: trait QueryUnit case class SimpleQuery(query: String,metadata: Metadata) case class ComplexQuery(Map[String,Seq[SimpleQuery]) case class API( query: Map[String,Seq[QueryUnit]] ) Map的元素将是conjuctions(ANDs),而Seq的元素将是析取(OR).我不想将Simple与ComplexQueries混合使用,我计划在Seq [QueryUnit]上进行模式匹配. 解决方法
试试这个(部分基于
this blog post from Miles Sabin):
// Your domain trait QueryUnit case class SimpleQuery(query: String,metadata: AnyRef) extends QueryUnit case class ComplexQuery(map: Map[String,Seq[SimpleQuery]]) extends QueryUnit // End of your domain // Something which has type parameter,so we can add QueryUnit,... trait WrongArg[T] // Create ambiguous implicits for QueryUnit implicit def v0: WrongArg[QueryUnit] = ??? implicit def v2: WrongArg[QueryUnit] = ??? // And valid values for the concrete subclasses implicit val simpleQWrongArg: WrongArg[SimpleQuery] = new WrongArg[SimpleQuery] {} implicit val complexQWrongArg: WrongArg[ComplexQuery] = new WrongArg[ComplexQuery] {} case class API[QU <: QueryUnit]( query: Map[String,Seq[QU]] // Require an evidence that we are getting the correct type )(implicit w: WrongArg[QU]) { } API/*[SimpleQuery]*/(Map("" -> Seq(SimpleQuery("","")))) API/*[ComplexQuery]*/(Map("" -> Seq(ComplexQuery(Map.empty)))) // Fails to compile because of ambiguous implicits //API(Map("s" -> Seq(SimpleQuery("","")),"c" -> Seq(ComplexQuery(Map.empty)))) 它不理想(名称错误,没有@implicitNotFound注释). 基本思想是我们为基类创建模糊的含义,但不为子类创建含糊不清的含义.由于隐式解析规则,这将仅针对子类进行编译,但不针对基类进行编译. 清理版本: @annotation.implicitNotFound("Base QueryUnit is not supported,you cannot mix SimpleQuery and ComplexQuery") trait Handler[T] extends (T => Unit) object API { implicit def baseQueryUnitIsNotSupported0: Handler[QueryUnit] = ??? implicit def baseQueryUnitIsNotSupported1: Handler[QueryUnit] = ??? implicit val simpleQWrongArg: Handler[SimpleQuery] = new Handler[SimpleQuery] { override def apply(s: SimpleQuery): Unit = {} } implicit val complexQWrongArg: Handler[ComplexQuery] = new Handler[ComplexQuery] { override def apply(s: ComplexQuery): Unit = {} } } case class API[QU <: QueryUnit](query: Map[String,Seq[QU]])( implicit handler: Handler[QU]) { // Do something with handler for each input } // Usage import API._ import scala.annotation.implicitNotFound API/*[SimpleQuery]*/(Map("" -> Seq(SimpleQuery("","")))) API/*[ComplexQuery]*/(Map("" -> Seq(ComplexQuery(Map.empty)))) // Error:(56,71) Base QueryUnit is not supported,you cannot mix SimpleQuery and ComplexQuery //API(Map("s" -> Seq(SimpleQuery("","c" -> Seq(ComplexQuery(Map.empty)))) 或者使用类型边界并隐式: case class API[QU <: QueryUnit: Handler](query: Map[String,Seq[QU]]) { def doSomething: Unit = for {(_,vs) <- query v <- vs} { val handler: Handler[QU] = implicitly[Handler[QU]] handler(v) } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |