2010-11-29 9 views
8

私は特性を拡張する実際のクラス を返す宣言されたメソッドを持つ密閉型の特性を持ちたいと思います。私は抽象型、パラメータ型、または を使用してこれを解決する他の良い方法がありますか?形質と型を拡張する

sealed trait Foo { 
    type T 
    def doit(other: T): T 
} 

又は

sealed trait Foo[T] { 
    def doit(other: T): T 
} 

Tは、この例でFooのサブタイプでなければならないことに留意されたいです。私はこのようにそれを行う場合はタイプ 情報があまりにも繰り返し感じている:

case class Bar(name: String) extends Foo[Bar] { 
    def doit(other: Bar): Bar = ... 
} 

答えて

2

trait Foo[T] { 
    self: T => 
    def doit: T => T 
} 

case class Bar(name: String) extends Foo[Bar] { 
    // note: types omitted 
    def doit = { other => Bar(name + other.name) } 
} 

それは抽象型で同じことを行うことは可能ではありません。

trait Foo { 
    self: T => // won't compile because T isn't defined yet 
    type T 
    def doit: T => T 
} 
1

EDIT - 以下は、私のオリジナルの答えです。あなたのコメントは、一致するタイプの任意のインスタンスを返すことを希望していることを示していますが、これは決して賢明ではないと私は本当に信じていません。 はそれがなかったと仮定し、T.type構文経由:

trait T { def foo : T.type } 

trait U extends T { def foo = new U } //must be a U 

class W extends U 

val w : W = (new W).foo //oh dear. 

これはthis.type経由で達成可能である。また、その後

scala> trait T { 
| def foo : this.type 
| } 
defined trait T 

scala> class W extends T { 
| def foo = this 
| } 
defined class W 

scala> (new W).foo 
res0: W = [email protected] 

scala> res0.foo 
res1: res0.type = [email protected] 

そして:

scala> ((new W) : T) 
res4: T = [email protected] 

scala> res4.foo.foo.foo 
res5: res4.type = [email protected] 
+0

は聞き覚え。おそらくこれの例を教えてください。 – chrsan

+0

同じタイプの新しいインスタンスを返すとうまくいかないようですか? – chrsan

+0

はい - 'this.type'はパスに依存します:現在のインスタンスを返すためにのみ有効です –

4

彼らは主に交換可能です。 Oderskyによると、その理由は主に完全性のためであった。メソッドやフィールド(値)は抽象的でもパラメータとして渡すこともできるので、型もそうである。

すべて同じ型名を使用する複数の形質を混在させる場合は、抽象型を使用する方が適しています。型パラメータを使用すると、明示的に各

に型を渡す必要があるここでは、このすべてを説明する記事です:http://www.artima.com/weblogs/viewpost.jsp?thread=270195

1
trait Foo[A <: Foo[A]] 

Aがfooのサブタイプである場合は、この形質はだけで混合することができ、[A]とそれを満たす唯一のタイプはFooクラスが混在しているクラスです。私はリフトのMapper特性でこの解決策を見た。

+0

あまりありません。'Class Bar extends Foo [Bar]'と 'class Baz extends Foo [Bar]'を試してみてください。 –

2

あなたが書くことができます。

trait Foo[T] { 
    self:T => 
    def doit(other: T): T 
} 

case class Bar(name: String) extends Foo[Bar] { 
    def doit(other: Bar): Bar = ... 
} 

あなたの例との違いは、バーは、他の方法(例えばcase class Bar(name: String) extends Foo[String])でインスタンス化することができないということです。あなたのdoit方法は、ファクトリ関数を返すことによって、多少の繰り返しを削減することができます

関連する問題