8

BaseサブクラスDerived1とを持つ抽象 Scala クラスがありDerived2ます。Base実装クラスと同じ型のオブジェクトを返す関数 f() を定義します。だからDerived1.f()戻りますDerived1Derived2.f()戻りますDerived2。これをScalaで書くにはどうすればよいですか?

これが私がこれまでに思いついたものです。

package com.github.wpm.cancan

abstract class Base {
  def f[C <: Base]: C
}

case class Derived1(x: Int) extends Base {
  def f[Derived1] = Derived1(x + 1)
}

case class Derived2(x: Int) extends Base {
  def f[Derived2] = Derived2(x + 2)
}

これにより、次のコンパイラ エラーが発生します。

type mismatch;
[error]  found   : com.github.wpm.cancan.Derived1
[error]  required: Derived1
[error]   def f[Derived1] = Derived1(x + 1)

type mismatch;
[error]  found   : com.github.wpm.cancan.Derived2
[error]  required: Derived2
[error]   def f[Derived2] = Derived2(x + 2)

このエラー メッセージは、このコンテキストcom.github.wpm.cancan.Derived1と同じである必要があるため、混乱を招きます。Derived1

4

2 に答える 2

15

Randall Schulz は、現在のコードが機能しない理由の 1 つを指摘しました。ただし、 F境界ポリモーフィズムを使用すると、必要なものを取得できます。

trait Base[C <: Base[C]] { def f: C }

case class Derived1(x: Int) extends Base[Derived1] {
  def f: Derived1 = Derived1(x + 1)
}

case class Derived2(x: Int) extends Base[Derived2] {
  // Note that you don't have to provide the return type here.
  def f = Derived2(x + 2)
}

ベース トレイトの型パラメータを使用すると、そこで実装するクラスについて話すことができます。たとえば、 の戻り値の型ですf

于 2013-02-07T00:29:11.863 に答える
8

(完全に良い)Travis Brownの答えについて少し精度を追加するだけです。実装クラスを参照Ctrait Base[C <: Base[C]]ましょう。subclass extends Base[subclass]それは、あなたがそうできるようにするための書き方の慣習に固執しているだけです。このタイプを参照する方法を私が知っている方法はありません。私が意味することを明確にするために、これはコンパイルします

trait Base[C <: Base[C]] { def f: C }

case class Derived1(x: Int) extends Base[Derived1] {
  def f: Derived1 = Derived1(x + 1)
}
// a Derived2 where f returns Derived1!!
case class Derived2(x: Int) extends Base[Derived1] {
  def f = Derived1(x + 2)
}

さて、実装として持つのBaseがケースクラスだけの場合は、自己型の境界を介してこれを正しく取得できます。

trait Base[C <: Base[C]] { self: C => 
  def f: C 
}

case class Derived1(x: Int) extends Base[Derived1] {
  def f: Derived1 = Derived1(x + 1)
}
// a Derived2 where f returns Derived1!!
// this won't compile now
case class Derived2(x: Int) extends Base[Derived1] {
  def f = Derived1(x + 2)
}
于 2013-02-07T15:53:19.133 に答える