2016-10-06 23 views
0

我想這樣做如下:如何使用變量作爲Scala類型參數?

val aoeu = List((0, 1), (0, 1, 2)) 
List(Tuple2, Tuple3).foreach { snth => 
    println(aoeu.filter(_.isInstanceOf[snth]).map(_.asInstanceOf[snth])) 
} 

這可能嗎?

+0

是的,但它變得複雜並且破壞了編譯時類型的安全性。請參閱https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20#.8ohbqsjqg – spiffman

+0

在Scala中,使用implicits很容易傳入一個類型並獲取值;但傳遞一個值並返回一個類型更難(和不安全)。在你的例子中,如果你用'type snth = Product'替換'val snth = Product',除了運行時錯誤,因爲你要將一個'Boolean'轉換爲'Product',它可以工作。你的實際目標是什麼? – Yawar

+0

正如@Yawar在你改成'type snth = Product'後指出的那樣,'aoeu.isInstanceOf [snth]'是一個布爾值,因此你不能將它作爲'snth'的一個實例來操作。 –

回答

0

正如我所提到的那樣,Scala中的類型安全和(相對)容易傳遞一個類型參數並返回一個值。什麼是艱難的,而不是編譯時類型安全的,是另一回事。對於你的問題,答案是......有點兒。我們可以做的是定義一個類型類來捕獲安全轉換的想法,爲我們感興趣的類型設置一些實例,然後執行我們的操作。因此,這裏是我有:

import scala.util.Try 

/** 
A typeclass to represent safe casting behaviour. 
*/ 
trait HasInstance[A] { def apply(any: Any): Option[A] } 

object HasInstance { 
    /** 
    A helper to quickly create a typeclass instance. 
    */ 
    private class Impl[A](_apply: Any => Option[A]) 
    extends HasInstance[A] { 
    override def apply(any: Any): Option[A] = _apply(any) 
    } 

    /* Instances for standard types. */ 

    implicit val int: HasInstance[Int] = 
    new Impl(any => Try(any.asInstanceOf[Int]).toOption) 

    implicit def tuple2[A, B]: HasInstance[Tuple2[A, B]] = 
    new Impl(any => Try(any.asInstanceOf[Tuple2[A, B]]).toOption) 

    implicit def tuple3[A, B, C]: HasInstance[Tuple3[A, B, C]] = 
    new Impl(any => Try(any.asInstanceOf[Tuple3[A, B, C]]).toOption) 
} 

object Test { 
    def test(): Unit = { 
    val xs = List((0, 1), (0, 1, 2)) 

    // Flatmap will automatically filter out `None` values. 

    println(xs flatMap implicitly[HasInstance[Tuple2[Int, Int]]].apply) 
    // ==> List((0, 1)) 

    println(
     xs flatMap implicitly[HasInstance[Tuple3[Int, Int, Int]]].apply) 
    // ==> List((0, 1, 2)) 
    } 
} 

注意,我們仍然無法捕捉的實例在列表中,因爲它們的類型將迫使斯卡拉上溯造型到AnyRef將它們存儲起來。如果你想擁有和映射不同種類的列表,你就處於無形狀態的領域。實際上,您可能無論如何都是因爲您可能想要進行泛型派生,以便爲HasInstance輕鬆派生實例。