简体   繁体   中英

Scala Queue & PriorityQueue base trait

Is there any reason why collection.mutable.Queue and collection.mutable.PriorityQueue don't share something like QueueLike base trait in the Scala standard library ? The enqueue & dequeue methods appear to have the same signatures. Why aren't the classes interchangeable as queue containers, or am I missing something ?

Perhaps this deserves to be an answer, not just a comment...

What version of Scala are you using? I checked the 2.10, 2.9, 2.8 and 2.7 API docs and none of them have a QueueLike trait. If the question is about the concept of a common QueueLike trait that could be shared by both immutable and mutable implementations, there's a problem: Mutable classes are all invariant in their contained type parameters. The immutable collection classes are all covariant in their contained type parameter. Any API member that involves values of the contained type, whether as arguments or a return type, cannot be shared by both immutable and mutable implementations.

Round Two:

package rrs.scribble


import  scala.collection.mutable.{Queue, PriorityQueue}
import  scala.math.Ordering

trait   QueueOps[T]
{
  def dequeue(): T
  def enqueue(elems: T*): Unit
}


object  UniQueue
{
  sealed trait QSel
  object PrioQ extends QSel
  object PlainQ extends QSel

  def apply[T : Ordering](kind: QSel): QueueOps[T] =
    kind match {
      case PrioQ  => new PriorityQueue[T]() with QueueOps[T]
      case PlainQ => new Queue[T]() with QueueOps[T]
    }
}

object  UQTest
{
  import UniQueue._

  def main(args: Array[String]) {
    val prq1 = UniQueue[Int](PrioQ)
    val plq1 = UniQueue[Int](PlainQ)

    prq1.enqueue(1, 4, 9)
    plq1.enqueue(9, 4, 1)
    val prq2 = UniQueue[Int](PrioQ)
    val plq2 = UniQueue[Int](PlainQ)

    printf("prq1: dequeue=%d; dequeue=%d; dequeue=%d%n", prq1.dequeue, prq1.dequeue, prq1.dequeue)
    printf("plq1: dequeue=%d; dequeue=%d; dequeue=%d%n", plq1.dequeue, plq1.dequeue, plq1.dequeue)

    prq2.enqueue(9, 4, 1)
    plq2.enqueue(1, 4, 9)
    printf("prq2: dequeue=%d; dequeue=%d; dequeue=%d%n", prq2.dequeue, prq2.dequeue, prq2.dequeue)
    printf("plq2: dequeue=%d; dequeue=%d; dequeue=%d%n", plq2.dequeue, plq2.dequeue, plq2.dequeue)
  }
}

Running this in SBT:

> run
[info] Running rrs.scribble.UQTest 
prq1: dequeue=9; dequeue=4; dequeue=1
plq1: dequeue=9; dequeue=4; dequeue=1
prq2: dequeue=9; dequeue=4; dequeue=1
plq2: dequeue=1; dequeue=4; dequeue=9

However, you'll find that as written, there are only two things you can do with the value returned from UniQueue.apply() and that is call enqueue and dequeu . You have to copy every other method signature you want to be able to use to trait QueueOps[T] and if there are any with variant signatures you won't be able to do that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM