0

どうすればこれを達成できますか:

final case class ChairId(id: String)

trait GeneratorLike[TO, TC <: AbstractId] {
  val prefix: String
  def generate(): TC = TO.apply(prefix + "-" + UUID.randomUUID())
}

implicit object ChairIdGenerator extends GeneratorLike[ChairId.type, ChairId] {
  val prefix: String = "CHAIR"
}

implicit def IdFn[TO, TC <: AbstractId](x: TO)(implicit ev: GeneratorLike[TO, TC]): GeneratorLike[TO, TC] = ev

//right now I can call:
ChairId.generate()

その状況でコンパニオン オブジェクトを定義したくありません。暗黙を使用してオブジェクトを拡張する機会があるかどうか疑問に思いましたか?

私がそうするとき (私は TypeObject として TO を使用し、TypeClass 命名として TC を使用します)、idFn[TO, TC]TO を実装するオブジェクトにしたいのですが、def apply(id: String): TCそれを強制できますか? また、この機能を使用するにはどうすればよいですか? 型パラメーターで関数を呼び出すことはまったく不可能だと感じています:/

4

2 に答える 2

2

型パラメータはobjectではなくを表しているため、型パラメータでメソッドを呼び出すことできません。オブジェクトは存在するものであるため、オブジェクトでメソッドを呼び出すことができますが、型は抽象的な概念です。コンパニオンオブジェクトに暗黙的に追加したいというあなたの動機が何であるかはわかりません。実際には、のコンパニオンを定義するのと同じくらい多くのコードを暗黙的に定義する必要があるためです。generate()GeneratorLikeChairId

メソッド ( case class で実装できる)を強制GeneratorLikeし、最初の型パラメーターを削除すると、これは機能します。applyapply

trait GeneratorLike[TC <: AbstractId] { this: Singleton =>
  val prefix: String
  def apply(id: String): TC
  def generate(): TC = apply(prefix + "-" + UUID.randomUUID())
}

abstract class AbstractId

final case class ChairId(id: String) extends AbstractId

object ChairId extends GeneratorLike[ChairId] {
  val prefix = "CHAIR"
}

scala> ChairId.generate()
res0: ChairId = ChairId(CHAIR-60bb01c7-af95-46c7-af45-0b3fa78b3080)
于 2016-07-31T17:29:16.550 に答える
0

構造型付けは、JVM では特に良い考えではありませんdef test(x: {def apply(s: String)}): TC。リフレクションを使用して実装されているため、型の使用は常に避けるようにしてください。

val第二に、おそらくa 内での使用は避けるべきtraitです。ここを読んでください。

あなたが検討したアプローチは、実際には正しいもの、つまり型クラスです。

trait HasGenerator[T] {
  def apply(uuid: String): T 
  def generate[T : Generator] = apply(Generator[T].generate)
}

final case class ChairId(id: String) 

object ChairId extends HasGenerator[ChairId]

trait Generator[TO] {
  def prefix: String
  def generate(): String = prefix + "-" + UUID.randomUUID()
  def apply(): String = generate
}

object Generator {
  def apply[T : Generator] = implicitly[Generator[T]]
}

// Notice .type is not necessary
implicit object ChairIdGenerator extends Generator[ChairId] {
  override def prefix = "CHAIR"
}

なぜ使用しないのですか:

ChairId(Generator[ChairId])

これはやり過ぎのように思えますが、何とか簡単にできます。型クラスはまだそれほど必要ではないように思われるため、要件をもう少し具体化する価値があります。あなたはただ行うことができます:

アップデート

上記で追加したようなものをHasGeneratorコンパニオン オブジェクトと組み合わせて使用​​すると、正常に呼び出すことができます。ChairId.generate()

于 2016-07-31T19:49:46.167 に答える