Scala Builder Pattern:涉及T类型的非法循环引用

时间:2014-06-11 22:20:44

标签: class scala generics override

我试图为我的User类层次结构编写一些通用构建器。 我有一个特点,UserBuilder和每个"与"特征中的方法必须返回与当前类相同的类型。因此,如果我在ComplexUserBuilder中,则withId方法应返回ComplexUserBuilder,而不是UserBuilder。

但是我得到了

  

涉及类型T的非法循环引用

有没有办法解决这个问题?

这是我的代码:

trait UserBuilder[T >: UserBuilder[T]] {

  var id: String = ""

  def withId(id: String): T = {
    this.id = id
    return this
  }
}

class ComplexUserBuilder extends UserBuilder[ComplexUserBuilder] {

  var username: String = ""

  def withUsername(username: String): ComplexUserBuilder = {
    this.username = username
    return this
  }

  def build = new ComplexUser(id, username)
}

顺便说一句,如果我将trait UserBuilder[T >: UserBuilder[T]]替换为trait UserBuilder[T >: UserBuilder[_]],我会得到:

  

类型参数[model.ComplexUserBuilder]不符合特征UserBuilder的类型参数边界[T>:model.UserBuilder [_]]

更新

trait UserBuilder[T >: UserBuilder[T]]

应该是(如GClaramunt建议的那样)

trait UserBuilder[T <: UserBuilder[T]]

但现在有一个丑陋的演员作为返回类型

3 个答案:

答案 0 :(得分:4)

要使UserBuilder子类具有对自己类型的引用,您应该声明this的类型(并使它们 sub -types,而不是超级 -types,UserBuilder):

trait UserBuilder[T <: UserBuilder[T]] { this: T =>
  ...
}

答案 1 :(得分:4)

丹已经很清楚地解决了你的问题。我想说的是,通过使用scala的this.type特性,你甚至根本不需要泛型T.

trait UserBuilder {

  var id: String = ""

  def withId(id: String): this.type = {
    this.id = id
    return this
  }
}

class ComplexUserBuilder extends UserBuilder {

  var username: String = ""

  def withUsername(username: String): this.type = {
    this.username = username
    return this
  }

  def build = new ComplexUser(id, username)
}

并且,如果要将构建方法添加到UserBuilder特征,您可能需要添加泛型类型U来约束用户类型,例如

trait UserBuilder[U <: { def id: String }] {

  var id: String = ""

  def withId(id: String): this.type = {
    this.id = id
    return this
  }

  def build: U
}

class ComplexUserBuilder extends UserBuilder[ComplexUser] {

  var username: String = ""

  def withUsername(username: String): this.type = {
    this.username = username
    return this
  }

  def build = new ComplexUser(id, username)
}

答案 2 :(得分:1)

我不确定你想要达到的是什么,但你有向后的上限类型限制应该是&#34;&lt;:&#34;而不是&#34;:&gt;&#34;

产品:&gt;是一个较低类型的绑定限制,意思是,T必须是UserBuilder的超类型,你想要一个子类型(所以你可以扩展UserBuilder)

trait UserBuilder[T <: UserBuilder[T]] {
    self: T =>

    var id: String = ""

    def withId(id: String): T = {
      this.id = id
      this
    }
  }

  class ComplexUserBuilder extends UserBuilder[ComplexUserBuilder] {

    var username: String = ""

    def withUsername(username: String): ComplexUserBuilder = {
      this.username = username
      this
    }

    //def build = new ComplexUser(id, username)
  }

此外,您不需要&#34;返回&#34;,(几乎)Scala中的所有内容都是一个返回值的表达式。