2014-10-16 49 views
0

調用假設我有像以下代碼:指定的方法來對未知的一般類型

abstract class GenericType[T]{ 
    val someSeq: Seq[T] 

    def list() = for(item <- someSeq) println(item) 
} 

class ConcreteType extends GenericType[Int] { 
    val someSeq = Seq(1, 2, 3) 
} 

object MyApp { 
    def main(args: Array[String]) { 
     val ct = new ConcreteType 
     ct.list() 
    } 
} 

即簡單地打印出1 2 3(在不同的行)。但是,假設我想創建一個調用T方法的泛型類型實例。例如,假設我想調用整數的max方法。我將如何指定要調用的方法?

我認爲我可以在抽象類中創建一個值,該類包含調用每個item的方法並在具體類中指定該方法。

因此,換句話說,我想是這樣結束了:

abstract class GenericType[T]{ 
    val someSeq: Seq[T] 
    val methodToCall: ??? 

    def list() = for(item <- someSeq) println(item.methodToCall) 
} 

class ConcreteType extends GenericType[SomeType] { 
    val someSeq = Seq(1, 2, 3) 
    val methodToCall = ???.max(_, 2) 
} 

而且期望main來然後打印出2 2 3(即,for(item <- someSeq) println(item.max(_, 2))結果)。

+0

當然,一個解決方案是使用反射和指定要調用的方法的字符串名稱,但這有我想避免的性能問題。 – Mike 2014-10-16 17:53:55

回答

0

你需要指定「mtehodToCall」的返回類型,我用T代表例如

abstract class GenericType[T]{ 
    def someSeq: Seq[T] 
    def methodToCall: T => T 

    def list() = for(item <- someSeq) println(methodToCall(item)) 
    } 

    class ConcreteType extends GenericType[Int] { 
    val someSeq = Seq(1, 2, 3) 
    val methodToCall: Int => Int = math.max(_, 2) 
    } 

    new ConcreteType().list() 
+0

上面的'max'只是一個例子。實際上我試圖調用一些'T'的方法(我已經知道類型簽名了)。 – Mike 2014-10-16 17:51:45

3

你不能做到這一點。你只能返回值,而方法不是值。但是,您可以使用一個函數並傳遞一個lambda或通過η-expansion將該方法轉換爲一個函數。

abstract class GenericType[T] { 
    def someSeq: Seq[T] 

    type MapResult 
    def map: T => MapResult 

    def list() = someSeq.foreach(map andThen println) 
} 

class ConcreteType extends GenericType[Int] { 
    override val someSeq = Seq(1, 2, 3) 

    override type MapResult = Int 
    override val map = 2.max(_) 
} 
1

我會親自嘗試使用類型類。這裏是一個例子:

trait MethodToCall[T, R] { 
    def invoke(obj: T): R 
    } 

    implicit object IntToCall extends MethodToCall[Int, Int] { 
    override def invoke(obj: Int): Int = obj.max(2) 
    } 

    abstract class GenericType[T]{ 
    def someSeq: Seq[T] 

    def list[R](implicit mtc: MethodToCall[T, R]) = 
     for(item <- someSeq) println(mtc.invoke(item)) 
    } 

    class ConcreteType extends GenericType[Int] { 
    val someSeq = Seq(1, 2, 3) 
    } 

    new ConcreteType().list[Int] 
相關問題