简体   繁体   English

Scala Queue和PriorityQueue基本特征

[英]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 ? 是否有任何理由为什么collection.mutable.Queuecollection.mutable.PriorityQueue不会在Scala标准库中共享类似QueueLike基本特征的东西? The enqueue & dequeue methods appear to have the same signatures. enqueuedequeue方法似乎具有相同的签名。 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? 您使用的是什么版本的Scala? I checked the 2.10, 2.9, 2.8 and 2.7 API docs and none of them have a QueueLike trait. 我检查了QueueLike和2.7 API文档,但没有一个具有QueueLike特性。 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. 如果问题是关于可以由不可变和可变实现共享的常见QueueLike特性的概念,则存在一个问题:可变类在其包含的类型参数中都是不变的。 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. 任何涉及所包含类型的值的API成员,无论是作为参数还是返回类型,都不能由不可变和可变实现共享。

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: 在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 . 但是,你会发现,只要写了一些东西,你就可以用UniQueue.apply()返回的值来做两件事,那就是调用enqueuedequeu 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. 您必须复制您希望能够用于trait QueueOps[T]所有其他方法签名,如果有任何变体签名,您将无法执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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