scala中的循环类型参数定义

par*_*tic 4 generics scala type-parameter

我试图定义一个通用容器,其元素可以返回封闭容器.就像是:

abstract class Container[E <: Element] { // compile error
  def contains( e: E ): Boolean
  def addNewElement(): Unit
}

abstract class Element[C <: Container] { // compile error
  def enclosingContainer(): C
}

class MyContainer extends Container[MyElement] {
  private var elements = List[MyElement]()
  override def contains( elem: MyElement ) = elements.contains( elem )
  override def addNewElement() { elements ::= new MyElement(this) }
}

class MyElement( container: MyContainer ) extends Element[MyContainer] {
  override val enclosingContainer = container
}
Run Code Online (Sandbox Code Playgroud)

但是,这种片段不编译,因为我应该给一个类型参数Elementabstract class Container[E <: Element]定义和类型Containerabstract class Element[C <: Container]定义.

我有办法实现我正在寻找的行为吗?是否有适当的声明ContainerElement?我应该定义第三方对象吗?

Dan*_*ral 6

abstract class Container[E <: Element[_]] {
  def contains( e: E ): Boolean
  def addNewElement(): Unit
}

abstract class Element[C <: Container[_]] {
  def enclosingContainer(): C
}

class MyContainer extends Container[MyElement] {
  private var elements = List[MyElement]()
  override def contains( elem: MyElement ) = elements.contains( elem )
  override def addNewElement() { elements ::= new MyElement(this) }
}

class MyElement( container: MyContainer ) extends Element[MyContainer] {
  override val enclosingContainer = container
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*nov 6

已经给出的其他解决方案无法强制类型匹配:即,给定类型ContainerImpl extends Container,您应该确定ContainerImpl.E.C应该是ContainerImpl而不是其他容器.这是一个强制执行此操作的(改编自http://programming-scala.labs.oreilly.com/ch13.html):

abstract class ContainerWithElement {
  type C <: Container
  type E <: Element

  trait Container {
    self: C =>
    def contains( e: E ): Boolean
    def addNewElement(): Unit
  }

  trait Element {
    self: E =>
    def enclosingContainer(): C
  }
}
Run Code Online (Sandbox Code Playgroud)


Mit*_*ins 5

使用类型成员而不是类型参数可以避免此问题:

abstract class Container { // compile error
  type E <: Element
  def contains( e: E ): Boolean
  def addNewElement(): Unit
}

abstract class Element { // compile error
  type C <: Container
  def enclosingContainer(): C
}

class MyContainer extends Container {
  type E = MyElement
  private var elements = List[MyElement]()
  override def contains( elem: MyElement ) = elements.contains( elem )
  override def addNewElement() { elements ::= new MyElement(this) }
}

class MyElement( container: MyContainer ) extends Element {
  type C = MyContainer
  override val enclosingContainer = container
}
Run Code Online (Sandbox Code Playgroud)