简体   繁体   中英

“new” Keyword doesn't work with immutable Queue

I tried to create a Queue with new Keyword..I did it for both mutable and immutable Queue.

But when I tried with immutable Queue, it gives error :

<console>:8: error: constructor Queue in class Queue cannot be accessed in object $iw
 Access to protected constructor Queue not permitted because
 enclosing class object $iw in object $iw is not a subclass of 
 class Queue in package immutable where target is defined
       val a=new Queue[Int]()
             ^

scala> import scala.collection.immutable.Queue
import scala.collection.immutable.Queue

scala> val a=new Queue[Int]()
<console>:8: error: constructor Queue in class Queue cannot be accessed in object $iw
 Access to protected constructor Queue not permitted because
 enclosing class object $iw in object $iw is not a subclass of 
 class Queue in package immutable where target is defined
       val a=new Queue[Int]()

But when I tried this code with mutable Queue, immutable Stack, mutable Stack...It works well

scala> import scala.collection.mutable.Queue
import scala.collection.mutable.Queue

scala> val a=new Queue[Int]()
a: scala.collection.mutable.Queue[Int] = Queue()



scala> import scala.collection.immutable.Stack
import scala.collection.immutable.Stack

scala> val a=new Stack[Int]()
a: scala.collection.immutable.Stack[Int] = Stack()


scala> import scala.collection.mutable.Stack
import scala.collection.mutable.Stack

scala> val a=new Stack[Int]()
a: scala.collection.mutable.Stack[Int] = Stack()

Can anyone tell me, why is it so ???

From a quick look at the sourcecode , I would venture that the immutable version is essentially implemented through a couple of List s which pivots as needed to give nice performance between reads and writes (queue/dequeue).

This is quite dissimilar from the other collections, in that it needs both mentioned List s as parameters to the class constructor.
The companion object, on the other side, provides a public factory method that is consistent with other collections, by accepting a variable number of initial values for the Queue content.

What is missing is a public constructor for the class, that would mimic the companion-object apply call, by taking the initial values, and using them to build the "enque/dequeue" Lists .

Maybe it was not deemed essential, or it's been an oversight, or there is a deeper issue that I can't figure out.

The compiler already tells you why it doesn't work, because the conctructor is protected . You have to use the apply method of the companion to create an immutable.Queue :

val queue = immutable.Queue(1,2,3)

I'll interpret the question as "why is the constructor protected". We can only guess, but I tend to think it is a simple oversight. As a matter of style it is often better to use the companion objects to instantiate collections, but given that you can also directly instantiate other concrete collections, this should be doble with Queue . In other words, I definitely think that Queue should have this no arg contructor to create an empty queue, if only as a matter of consistency:

class Queue[+A] extends ... {
  ...
  def this() { this( Nil, Nil ) }
  ...
}

It is very subjective though.

I would guess that because it is encouraged to use empty to create void immutable collection, as it avoids overhead (if you do this multiple times) and exploit the immutability most. Just no need to create new instance every single time, because "there is only one empty queue in the world". For the mutable collection, it is obvious that this does not work.

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