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 {さらに2つの間違いがあります:
    1. そうではありextendsませんwith。後者は、いくつかの基本クラス/特性からすでに拡張した後にのみ使用されます。
    2. BaseCrudここで指定する必要がある型パラメーターが必要なので、次のようなものですBaseCrud[Customer]
  • そして最後に、実際の質問に答えるために:型パラメーターTとコンパニオンオブジェクトの間には大きな違いがあります。これらは本質的に異なるものであるため、 を介してコンパニオン オブジェクトにアクセスすることはできませんT.something。代わりに、たとえば抽象フィールドなど、他の方法でトレイトにコンパニオン オブジェクトを提供する必要があります。

これがあなたがやりたいと私が信じていることのバージョンです:

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

self特性でscala型を使用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 に答える