2011-05-12 6 views
4

は私がtuplingトリックを使用して、任意のアリティの機能をサポートし、次のFooクラスを持っているとします複数のアリティのScalaのジェネリッククラスの支持機能

abstract class Foo[T, R] { 
    def pull: T => R 
} 

私は、次の構文を使用してサブクラスを定義することができます。

implicit def function2Tofunction1[T1, T2, R](f: (T1, T2) => R): ((T1, T2)) => R = { 
    f.tupled 
} 

class Moo extends Foo[(Int, Int), Int] { 
    def pullImpl(x: Int, y:Int):Int = x + y 
    def pull = (pullImpl _) // implicit converts to tupled form 
} 

val m = new Moo() 
m.pull(4, 5) 

これはかなりclunkyです。理想的な構文は、次のようになります。

class Moo extends Foo[(Int, Int), Int] { 
    def pullImpl(x: Int, y:Int):Int = x + y 
} 

これを達成するために私の基本クラスを定義する方法はありますか?あなたはこの方法ではなく、関数として実装を定義して満足することができる場合

答えて

4

、その後、この作品:

abstract class Foo[T, R] { 
    type Fn = T => R 
    val pull: Fn 
} 

class Moo extends Foo[(Int, Int), Int] { 
    // The type has to be explicit here, or you get an error about 
    // an incompatible type. Using a type alias saves typing out 
    // the whole type again; i.e. ((Int, Int)) => Int 
    lazy val pull: Fn = (x: Int, y: Int) => x + y 
} 

をそうでなければ、私はあなたが別のアリティの実装メソッドのシグネチャをサポートするために、より多くの機械を必要とすると思います:

trait Foo[T, R] { 
    type Fn = T => R 
    val pull: T => R 
} 

trait FooImpl2[T1, T2, R] extends Foo[(T1, T2), R] { 
    lazy val pull: Fn = (pullImpl _).tupled 
    protected def pullImpl(x: T1, y: T2): R 
} 

// similarly for FooImpl3, FooImpl4, ... 

class Moo extends FooImpl2[Int, Int, Int] { 
    protected def pullImpl(x: Int, y: Int) = x + y 
} 
関連する問題