2016-09-04 8 views
0

私は多くの異なる方法で実装される抽象クラスを持っています。これらの実装者のいずれかをパラメータとしてとり、同じ型の新しいインスタンスを返すメソッドを作成しようとしています。私は抽象型(各実装者で適切に設定される)の新しいオブジェクトを生成するメソッドに "ファクトリ"関数を渡すことによってこの動作を実装しようとしています。抽象型パラメータをファクトリ関数で使用して、正しい型の新しいオブジェクトを生成する

私は故障に私は次のコードの中に抱えている問題を試してみた:

私の親抽象クラス:

class Child(x: Int) extends Parent(x) { 
    type Self = Child 

    override def factory: Int ⇒ Self = { 
    (v: Int) ⇒ new Child(v) 
    } 

    override def me = "Child" 
} 

abstract class Parent(val x: Int) { 
    type Self <: Parent 

    def factory: Int ⇒ Self 

    def me = "Parent" 
} 

子クラスの例

メソッドが正しい型のオブジェクトを生成するための方法として、型パラメータSelfを使用しようとしています。

今の方法自体:I変換方法に工場を渡すしようとしたとき、私はコンパイルエラーを取得

class Transformer[T <: Parent] { 

    var everyone: List[T#Self] = List.empty 

    def start() = { 
    val updated = for (e ← everyone) yield { 
     Parent.transform[T](e, e.factory) 
    } 

    everyone = updated 
    } 
} 

を:今、私は実際にこのすべてを配線しようとすると、

object Parent { 
    def transform[T <: Parent](input: T#Self, factory: (Int ⇒ T#Self)): T#Self = { 
    //do stuff with input 
    input.me 
    val result = 123 
    factory(result) 
    } 
} 

私はGEに物事の多様性を試してみた

Type mismatch, expected (Int) => T#Self, actual (Int) => Parent.this.Self

これはうまくいくが運がない。私はまだこのことに新しいので、おそらく(おそらく)私はここで何か狂ったことをしようとしている可能性があります。より良い選択肢は大いにありがたく思うが、私はまだこのようなものを得ることが可能かどうかを見ることに興味がある。最終目標は、transformメソッドがパラメータとして提供されたものと全く同じ型の新しいインスタンスを生成する方法を持つことです。

ご協力いただきまして誠にありがとうございます。ありがとう!

答えて

1

ファクトリメソッドが正しい型のオブジェクトを生成するための方法として、Self型パラメータを使用しようとしています。

これはtpolecatのReturning the "Current" Type in Scalaのことを思い出す:

私は型階層を持っている...どのように私は、「現在の」型を返すスーパータイプのメソッドを宣言していますか?

我々はF-有界タイプを適応させることができ、あなたのParentChild階層にそのポストで議論アプローチ:

trait Parent[A <: Parent[A]] { this: A => 

    def x: Int 

    def factory: Int ⇒ A 

    def me = "Parent" 
} 

class Child(override val x: Int) extends Parent[Child] { 

    override def factory = (v: Int) ⇒ new Child(v) 

    override def me = "Child" 
} 

class OtherChild(override val x: Int) extends Parent[OtherChild] { 

    override def factory = (v: Int) ⇒ new OtherChild(v) 

    override def me = "OtherChild" 
} 

object Parent { 
    def transform[A <: Parent[A]](input: A): A = { 
    //do stuff with input 
    input.me 
    val result = 123 
    input.factory(result) 
    } 
} 

そして、Bonus Round: How do we deal with collections?セクション以下、あなたのTransformerはこのようなものになり

class Transformer { 

    import scala.language.existentials 

    var everyone = List[A forSome { type A <: Parent[A] }](new Child(1), new OtherChild(2)) 

    def start() = { 
    val updated = everyone.map(Parent.transform(_)) 

    everyone = updated 
    } 
} 
+0

ワウありがとう!その投稿は素晴らしい読書でした。 – Vikram

関連する問題