繁体   English   中英

在扩展scala中的特征时,如何创建新的特定类型的类

[英]How can I create a new specific type of class when extending a trait in scala

我有一个特性,其中(除其他外)我想要一个方法来创建一个新的类实例,然后还有其他方法使用该类的实例。

我的代码的一个非常简化的版本是:

trait A {
  def prev: A
  def get(end: A): A
}

class B extends A {
  def prev: B = new B()
  def get(end: B): B = end.prev
}

我想在这里展示的是,next将返回一个新的类实例(实际上有一些新的构造函数参数),get方法将在内部使用next(以及其他逻辑)

上面的问题是编译器说“B类必须实现抽象成员get(end:A):A”,这是合理的。

我尝试使用类型边界解决它:

trait A {
  def prev: A
  def get(end: A): A
}

case class B extends A {
  def prev[TX <: A]: TX = new B()
  def get[TX <: A](end: TX): TX = end.prev
}

但现在错误是“B类型的表达式不符合预期的类型TX” new B()和“类型A的表达式不符合预期类型TX” end.prev

我不明白为什么这是一个问题,因为接下来返回一个B,它是A的子类型,这就是TX。

有没有办法实现我想做的事情?


如果上面的所有内容都显得过于抽象,请加上一些上下文。 我正在实施一个循环的双向链表,因为我找不到那样的东西。 特点包括:

trait Circular[T] {
  // Nodes in the list from the current position up to but NOT INCLUDING the end
  def toStream(end: Circular[T]): Stream[Circular[T]]
  def prev: Circular[T]
  ...

我的班级看起来像:

case class Node[T](val data: T, var prev: Node[T], var next: Node[T])

case class CircularList[T](first: Node[T], last: Node[T], current: Node[T]) 
  extends Circular[T] {

  // Nodes in the list from the current position up to but not including the end
  def toStream(end: CircularList[T]): Stream[CircularList[T]] = {
    @tailrec
    def toStreamRec(end: CircularList[T], acc: Stream[CircularList[T]]): Stream[CircularList[T]] = {
      if (this == end) {
        acc
      } else {
        toStreamRec(end.prev, Stream.cons(end.prev, acc))
      }
    }
    toStreamRec(end, Stream.empty)
  }

  def prev: CircularList[T] = new CircularList[T](first, last, current.prev)
  ...

所以toStream映射到get我在切开的例子。

你想要的是一种叫做F-bound泛型的东西。 代码如下:

trait Base[T <: Base[T]] {
  def next: T
  def get(end: T): T
}

class Chlid extends Base[Child] {
  def next: Chlid = new Chlid()
  def get(end: Chlid): Chlid = end.next
}

您的代码无法编译,因为

def get(end: B): B

不是重写

def get(end: A): A

因为原始方法接受类型A对象,而您的方法只需要更窄的类型B


对于你的Circular示例,你需要类似的东西

trait Circular[T, C <: Circular[T, C]] {
  // Nodes in the list from the current position up to but NOT INCLUDING the end
  def toStream(end: C): Stream[C]

  def next: C
}

case class Node[T](val data: T, var prev: Node[T], var next: Node[T])

case class CircularList[T](first: Node[T], last: Node[T], current: Node[T]) extends Circular[T, CircularList[T]] {

  // Nodes in the list from the current position up to but not including the end
  def toStream(end: CircularList[T]): Stream[CircularList[T]] = {
    @tailrec
    def toStreamRec(end: CircularList[T], acc: Stream[CircularList[T]]): Stream[CircularList[T]] = {
      if (this == end) {
        acc
      } else {
        toStreamRec(end.prev, Stream.cons(end.prev, acc))
      }
    }

    toStreamRec(end, Stream.empty)
  }

  def prev: CircularList[T] = new CircularList[T](first, last, current.prev)

  override def next: CircularList[T] = ???
}

暂无
暂无

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

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