1

ケースクラスのいくつかの一般的な属性、たとえば id やタイムスタンプを因数分解して、これらの汎用コードを記述したいと思います。以下は問題なく動作しますが、各ケース クラスですべての属性を繰り返す必要があります。

trait HasIdAndTimestamp {
  val id: Int
  val timestamp: Long
}
case class Client(id: Int, timestamp: Long, name: String) extends HasIdAndTimestamp
case class Order(id: Int, timestamp: Long, items: List[Int], clientId: Int) extends HasIdAndTimestamp
...

もう 1 つのオプションは、MetaData 型の単一のフィールドにこれらの共通フィールドを設定することです。

case class MetaData(id: Int, timestamp: Long)
trait HasMetaData {
  val metadata: MetaData
}
case class Client(metadata: MetaData, name: String) extends HasMetaData
case class Order(metadata: MetaData, items: List[Int], clientId: Int) extends HasMetaData
...

しかし、私はいつも .metadata.id を書くのはあまり好きではありません。また、これらのケース クラスを Slick を使用して DB に格納したいと考えています。このネストにより、テーブル定義に定型文が多数導入されます。次のようなものが欲しいです。

case class MetaData(id: Int, timestamp: Long)
case class Client(name: String) extends MetaData
case class Order(items: List[Int], clientId: Int) extends MetaData
...

Client と Order の両方にこれらの id とタイムスタンプ (val) フィールドがあり、それに応じて適用/適用解除が定義されています。

shapeless/scalaz はここで私を助けてくれますか?

4

1 に答える 1

2

これはどう?

// type def for Metadata
object MetadataType{ // singleton wrapper, because type defs can't be toplevel
  type MetaData = (Int,Long)
}
import MetadataType.Metadata

// unpack using pattern matching
class HasMetaData(metadata: Metadata) {
  val (id,timestamp) = metadata
}
case class Client(metadata: MetaData, name: String) extends HasMetaData(metadata)
case class Order(metadata: MetaData, items: List[Int], clientId: Int) extends HasMetaData(metadata)

// alternative: even avoid constructor argument
trait HasMetaData {
  def metadata: Metadata
  lazy val (id,timestamp) = metadata // lazy to avoid init order probs
}
case class Client(metadata: MetaData, name: String) extends HasMetaData
case class Order(metadata: MetaData, items: List[Int], clientId: Int) extends HasMetaData

次に、スリックで:

...
def * = ((id,timestamp), name) <> (Client.tupled, Client.unapply)
...

items: List[Int]確かではありませんOrder。別の関連テーブルの外部キーである場合は、ここにあるべきではありません。Order Table クラスは、正確に 1 つのデータベース テーブルを記述するためのものです。複数のテーブルからデータを集めたい場合は、代わりに (Order,List[Int]) 型の値として外部に書き込みます。クライアント側で後続の groupBy と結合するか、2 つの個別のクエリを使用して実装できます。ある時点で、Slick で実際にネストされたコレクションを返すそのような groupBy をサポートしたいと考えていますが、現時点ではクライアント側でそれを記述する必要があります。

于 2014-03-28T19:09:06.030 に答える