关于我的类型及其子类型的Iterable的隐式类

问题描述 投票:0回答:1

我正在尝试学习使用Scala的各种可能性来创建DSL的良好做法,但是我遇到了以下问题:我无法创建适用于Iterable的所有子类型(数组,列表, ...),并且仅匹配我定义的特定类型的子类型(在示例中:Fruit)。到目前为止,这是我想出的(这是我的代码的简化版本):

sealed trait Fruit { // My main type
  type A <: Fruit
  def setSize(v: Int): Unit = this match {
    case multi: MultiFruit[_] => multi.foreach(_.setSize(v))
    case or: Orange => or.size = v
    case ap: Apple => ap.size = v
    case _ => throw new Exception
  }
}
case class MultiFruit[F <: Fruit](var l: List[F]) extends Fruit {
  type A = F
  def foreach[B](f: F => B) : Unit = l.foreach(f)
}
case class Orange(var size: Int) extends Fruit {
  type A = Orange
}
case class Apple(var size: Int) extends Fruit {
  type A = Apple
}
object Fruit {
  implicit class IterableFruit[F <: Fruit, I <: Iterable[F]](val ite: I) extends AnyVal {
    def setSize(v: Int): Unit = ite.foreach(_.setSize(v)) // Apply setSize on every Fruit of the iterable
    def ++[F2 <: Fruit, I2 <: Iterable[F2]](ite2: I2): MultiFruit[_ <: Fruit] = new MultiFruit[Fruit](ite.toList++ite2.toList)
  }
}

所以这是我的问题:当我尝试运行此程序时

object Main {
  import Fruit._
  def main(args: Array[String]): Unit = {
    val oranges = Array.tabulate(5)(i => Orange(i*10))
    val apples = Array.tabulate(5)(i => Apple(i*10))
    oranges setSize 20 // setSize is not found, it doesn't match Iterable[Fruit]
    val or_ap = oranges ++ apples // ++ not found (the compiler wants to use the one defined in Array)
  }
}

找不到我的方法setSize和++。更让我感到困惑的是,我的IDE(IntelliJ)发现了setSize方法(并且没有报告任何错误),但IDE认为++是在Array中定义的,而不是在我的隐式类中定义的。我认为我的问题出在我键入IterableFruit类的方式上,但是我在扩展方法上发现的资源非常有限(而且从来没有真正深入过),而且我不知道出了什么问题。

编辑:另外,当我将隐式类修改为:

object Fruit {
  implicit class IterableFruit[F <: Fruit](val ite: Array[F]) extends AnyVal {
    def setSize(v: Int): Unit = ite.foreach(_.setSize(v)) // Apply setSize on every Fruit of the iterable
    def ++[F2 <: Fruit](ite2: Array[F2]): MultiFruit[_ <: Fruit] = new MultiFruit[Fruit](ite.toList++ite2.toList)
  }
}

一切都编译了,但是现在如果我尝试使用其他可迭代的变量而不是数组,显然就行不通了,所以我认为问题确实来自于我在隐式类中键入的方式

scala generics dsl
1个回答
0
投票

这可以通过将数组变成可迭代的方式来解决:

val oranges = Array.tabulate(5)(i => Orange(i*10)).toIterable
© www.soinside.com 2019 - 2024. All rights reserved.