6

因此,我希望有一个通用特征将一个类作为类型参数,该类具有从特定基类继承的伴随对象,并同时引用伴随对象和类本身。所以,

abstract class BaseModel[T] {
  def all: Seq[T]
}

case class Customer(email: String, password: String)

object Customer extends BaseModel[Customer]

// This trait is my issue
trait BaseCrud[T] { 
  def table[T](f: T => String): String = {
    T.all.map(f _).mkString("")
  }
}

object Controller with BaseCrud {
  def foo = table(_.email)
}

我有一些更接近该特征的解决方案,但我将其提炼出来,以便您可以看到我正在尝试做什么。

谢谢

更新

所以我从下面的弗兰克那里得到了解决方案,但我确实设法解决了我最初的难题。不过,在这种情况下,解决方案有点难看,为了完整起见,我将在此处包含它。

abstract class BaseModel[T] {
  def all: Seq[T] = Seq()
}

case class Customer(email: String, password: String)

object Customer extends BaseModel[Customer]

trait BaseCrud[T, U <: BaseModel[T]] { 
  def table(f: T => String)(implicit obj: U): String = {
    obj.all.map(f(_)).mkString("")
  }
}

object Controller extends BaseCrud[Customer, Customer.type] {
  implicit val model = Customer
  def foo = table(_.email)
}

因此类型参数更改为 BaseCrud,隐式添加到 BaseCrud.table 并在 Controller.model 中实现。我还修正了我所有的错别字。我发现它很有趣 Customer.type 似乎是伴生对象的类型。

4

2 回答 2

7

您的代码中有一堆问题..让我们一个接一个地解决它:

  • def table[T](...请注意,这会T覆盖方法范围的原始类型参数。不是你真正想要的,所以省略它并做这个def table(...
  • object Controller with BaseCrud {包含另外两个错误:
    1. 它必须extends不是with。后者仅在您已经从某些基类/特征扩展后使用。
    2. BaseCrud需要您必须在此处指定的类型参数,因此类似于BaseCrud[Customer]
  • 最后,回答您的实际问题:类型参数T和伴随对象之间存在巨大差异。它们本质上是不同的东西,所以你不能通过T.something. 相反,您需要以其他方式在您的 trait 中提供伴随对象,例如作为抽象字段。

这是我认为您想要做的一个版本:

abstract class BaseModel[T] {
  def all: Seq[T]
}

case class Customer(email: String, password: String)

object Customer extends BaseModel[Customer] {
  def all = List[Customer]() // have to define this
}

trait BaseCrud[T] {
  val companion : BaseModel[T]
  def table(f: T => String): String = {
    companion.all.map(f).mkString("")
  }
}

object Controller extends BaseCrud[Customer] {
  val companion = Customer
  def foo = table(_.email)
}
于 2012-05-09T08:16:07.057 回答
2

我认为,您可以在 trait 中使用 scalaself类型BaseCrud来指定应该混入的类。有关详细信息,请参阅链接问题

trait BaseCrud[T] {
  self: BaseModel[T] =>
  def table(f: T => String): String =
    all.map(f).mkString("")
}

object Controller extends BaseModel[Customer] with BaseCrud[Customer]{
  def foo = table(_.email)
}
于 2012-05-09T08:11:16.513 回答