简体   繁体   English

Scala中具有协变类型参数和私有构造函数的类

[英]Class with covariant type parameter and private constructor in Scala

Here is an example from the stairway book: 这是楼梯书的示例:

object Example {
  class Queue[+T] private (
                          private[this] var leading: List[T],
                          private [this] var trailing: List[T]
                            ) {
    private def mirror: Unit = {
      if(leading.isEmpty) {
        while(!trailing.isEmpty) {
          leading = trailing.head :: leading
          trailing = trailing.tail
        }
      }
    }

    // cannot resolve symbol U
    def this[U >: T](xs: U*) = this(xs.toList, Nil)
    // Covariant type T occurs in contra-variant position
    def this(xs: T*) = this(xs.toList, Nil)

    def head: T = {
      mirror
      leading.head
    }

    def tail: Queue[T] = {
      mirror
      new Queue(leading.tail, trailing)
    }

    def enqueue[U >: T](x: U) = new Queue[U](leading, x :: trailing)

    def size = leading.size + trailing.size
  }   
}

I added these lines: 我添加了以下几行:

    // cannot resolve symbol U
    def this[U >: T](xs: U*) = this(xs.toList, Nil)
    // Covariant type T occurs in contra-variant position
    def this(xs: T*) = this(xs.toList, Nil)

because I need some public constructors to create new Queues. 因为我需要一些公共构造函数来创建新的队列。 But each of these constructors has its problems (see the comments). 但是,每个构造函数都有其问题(请参阅注释)。 What can be done to solve them? 如何解决这些问题?


Update 更新

A constructor with no parameters seems to compile fine: 没有参数的构造函数似乎可以正常编译:

def this() = this(Nil, Nil)

In Scala, the prefered alternative to multiple contructors is to have a companion object with apply methods: 在Scala中,多个构造函数的首选替代方法是使用apply方法创建一个伴随对象:

object Queue {
  def apply[T, U <: T](xs: U*): Queue[T] = new Queue(xs.toList, Nil)
  def apply[T](xs: T*): Queue[T] = new Queue(xs.toList, Nil)
}

This way, you can instantiate your queues with val q = Queue(1, 2, 3) (note the absence of new ) as you would with most of the data structures in the Scala standard collection. 这样,您可以像使用Scala标准集合中的大多数数据结构一样,使用val q = Queue(1, 2, 3) (注意缺少new )实例化队列。

The object I wrote above will not compile as is because the two apply methods have same type after erasure, there are different ways around this issue, but in this precise example I think it's best to simply get ride of the second function. 我上面编写的对象不会按原样编译,因为擦除后这两个apply方法的类型相同,解决此问题的方式也不同,但是在这个精确的示例中,我认为最好简单地使用第二个函数。

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

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