Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Created September 11, 2012 07:33
Show Gist options
  • Save gakuzzzz/3696689 to your computer and use it in GitHub Desktop.
Save gakuzzzz/3696689 to your computer and use it in GitHub Desktop.
Case クラス固有のメソッドをトレイトで使いたい
case class User(id: String, name: String, options: Seq[String]) {
def options(os: String*): User = copy(options = options ++ os)
}
case class Group(id: String, name: String, subgroups: Seq[Group], options: Seq[String]) {
def options(os: String*): Group = copy(options = options ++ os)
}

↑ みたいに共通の options を持つ case class 郡があって、それぞれが copy を返す setter を持ってる。

けど全く DRY じゃない。

↓ みたいに trait で括りだしたいけど copy メソッドがそれぞれ違うため共通化できない。

なんか DRY にする方法はないものか?

trait Optional {
def options(os: String*): this.type = ...
}
case class User(id: String, name: String, options: Seq[String]) extends Optional
case class Group(id: String, name: String, subgroups: Seq[Group], options: Seq[String]) extends Optional
@gakuzzzz
Copy link
Author

reflection のコストを許容できるなら全然アリっすね!
ありがとうございます。

this.type 使えば T は要らないかもです。

trait Optional extends Cloneable { self: {val options: Seq[String]} =>
  override def clone(): this.type = super.clone().asInstanceOf[this.type]

  def options(args: String*): this.type = {
    val o = clone
    val f = o.getClass.getDeclaredField("options")
    f.setAccessible(true)
    f.set(o, options ++ args)
    o
  }
}
case class User(id: String, name: String, options: Seq[String]) extends Optional
case class Group(id: String, name: String, subgroups: Seq[Group], options: Seq[String]) extends Optional

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment