2011-05-12 32 views
4

假设我有以下类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) 

这非常笨重。理想的语法将如下所示:

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 
} 

否则,我想你会需要更多机械,以支持不同的arities实现方法签名:

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 
}