使用复合有界泛型类型扩展scala集合

时间:2013-04-03 22:29:01

标签: scala implicit-conversion scala-collections generic-collections higher-kinded-types

我对Scala很陌生,我觉得自己已经跳进了Scala的深渊。我需要编写一些(错误的,扩展的)集合(一个类似于ArrayBuffer,一个类似于Array),它们适用于通用(但有界)类型。我对如何解决这个问题有所了解,但完全有可能我的整个方法也是错误的。

我正在尝试做的事情的本质应该从下面的代码中清楚。我希望能够为每个由特定类型限定的组件对象创建“复合对象”的集合。在下面的代码中,Meal对象可以是Meal[Beef, Broccoli],但不能是Meal[Carrots, Broccoli]。然后,我想为复合对象创建两个集合类(类似Buffer和类似IndexedSeq)。作为参考,我一直在使用The Architecture of Scala Collections

package food

import collection.mutable.ArrayBuffer
import collection.{mutable, IndexedSeqLike}
import collection.generic.CanBuildFrom

// basic objects
abstract class Food {
  val isCooked: Boolean
}
abstract class Protein extends Food
abstract class Vegetable extends Food

case class Beef(isCooked: Boolean) extends Protein
case class Fish(isCooked: Boolean) extends Protein

case class Carrots(isCooked: Boolean) extends Vegetable
case class Broccoli(isCooked: Boolean) extends Vegetable

// Composite Object
class Meal[Protein, Vegetable](protein: Protein, vegetable: Vegetable)

// Buffer Container
class MealsBuffer[Protein, Vegetable] extends ArrayBuffer[Meal[Protein, Vegetable]]

// Fixed-Size Container
final class MealsSeq[Protein, Vegetable] private (data: Array[Meal[Protein, Vegetable]])
  extends IndexedSeq[Meal[Protein, Vegetable]]
  with IndexedSeqLike[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] {

  import MealsSeq._

  // Mandatory re-implementation of `newBuilder` in `IndexedSeq`
  override protected[this] def newBuilder: mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = MealsSeq.newBuilder

  // Mandatory implementation of `apply` in `IndexedSeq`
  def apply(idx: Int): Meal[Protein, Vegetable] = {
    if (idx < 0 || length <= idx)
      throw new IndexOutOfBoundsException
    data(idx)
  }

  def length: Int = data.size

}

// Fixed-Size Container Companion Object
object MealsSeq { 

  def fromBuffer(buf: MealsBuffer[Protein, Vegetable]): MealsSeq[Protein, Vegetable] = fromIndexedSeq(buf.toArray)

  def fromBuffer(buf: ArrayBuffer[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = fromIndexedSeq(buf.toArray)

  def fromIndexedSeq(buf: Array[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = new MealsSeq[Protein, Vegetable](buf)

  def fromSeq(buf: Seq[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = new MealsSeq[Protein, Vegetable](buf.toArray)

  def apply(bases: Meal[Protein, Vegetable]*) = fromSeq(bases)

  def newBuilder: mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = new ArrayBuffer mapResult fromSeq

  implicit def canBuildFrom: CanBuildFrom[MealsSeq[Protein, Vegetable], Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] =
    new CanBuildFrom[MealsSeq[Protein, Vegetable], Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] {
      def apply(): mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = newBuilder
      def apply(from: MealsSeq[Protein, Vegetable]): mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = newBuilder
  }
}

此代码无法编译,正如我所指出的,我特别在配对对象中遇到麻烦,特别是在单例对象中实现泛型。

正如我所说的那样,我对我最终制定的内容持开放态度而不是是我最终要完成的事情的正确解决方案。我应该以某种方式使用特征而不是抽象类吗?隐式转换而不是有界泛型和多态?有没有办法强制执行我正在尝试使用组合而不是复合Meals对象的继承?这在某种程度上是一个使用更高kinded类型的地方? Scala有很多,Java没有,我的脑袋有点旋转。

更新

为了澄清,我需要做的事情的范围如下:我需要两个集合,一个类似Array,一个类似ArrayBuffer。集合包含由一对子实体组成的实体,每个子实体具有特定限制。在这里的例子中,集合是用于仅由一种蛋白质和仅一种蔬菜组成的膳食。最终需要使用专门的行为和方法扩展集合,还能够覆盖特定的方法实现,以使它们对特定用例更有效。这就是任务的范围。我只是在寻找最简单的方法来实现它。

0 个答案:

没有答案