2016-08-29 20 views
0

したがって、キーの値を型を調べて返す暗黙のメソッドを追加したいとします。Scala Mapsに暗黙のgetAs()メソッドを追加する

import scala.reflect.ClassTag 

object MyMap { 
    implicit class FlexMap[A](map: Map[String, A]) { 
    def getAs[B](key: String)(implicit ct: ClassTag[B]): Option[B] = map.get(key) match { 
     case Some(value: ct.runtimeClass) => Some(value.asInstanceOf[B]) 
     case _ => None 
    } 
    } 
} 

しかし、私は試してみて、これをコンパイルすると、私が手:runtimeClassはscala.reflect.ClassTagのメンバーではありません

タイプ[B]

私は同じエラーを取得私が使っても:

case Some(value) if (value.isInstanceOf[ct.runtimeClass]) 

私はこれを回避する方法がわかりません。何か案は?

答えて

0

Scalaのa typeは値ではなく、異なるカテゴリに属しているため、メソッドから型を返すことはできません。 .runtimeClassは実際にはタイプが期待されるところでは使用できないタイプClassの値を返します。あなたはおそらく必要なのはこれです:

object MyMap { 
    implicit class FlexMap[A](map: Map[String, A]) { 
    def getAs[B](key: String)(implicit ct: ClassTag[B]): Option[B] = map.get(key) match { 
     case Some(value: B) => Some(value) 
     case _ => None 
    } 
    } 
} 

同じことを言って別の方法:

def getAs[B](key: String)(implicit ct: ClassTag[B]): Option[B] = 
    map.get(key) flatMap { 
    case value: B => Some(value) 
    case _  => None 
    } 
+0

これはコンパイルされますが、Scalaは 'Any'を' Int'と解釈しません。たぶん予想される動作ですが、動作させるにはどうすればいいですか?これが私の言うことです。 'Map [String、Any](" foo " - > 1).getAs [Int](" foo ")'は 'None'を返します。 – aa8y

+0

あなたのスニペットは私のために 'Option [Int] = Some(1)'を返します。 –

+0

2.10では動作していないようですが、2.11で動作しています。 – aa8y

1

ClassTagがあなたのために、実際の鋳造作業を行いunapply方法を持っており、オプションを返します。

implicit class FlexMap[A](map: Map[String, A]){               
    def getAs[B](key: String)(implicit ct: ClassTag[B]): Option[B] = 
    map.get(key).flatMap(ct.unapply)  
}                          
+0

これはScalaが私の例では 'case'を拡張しているのとまったく同じです。私はそれがあまりにも "低レベル"と考えられるべきなのだろうか? –

+0

これはコンパイルされますが、Scalaは 'Any'を' Int'として解釈しません。たぶん予想される動作ですが、動作させるにはどうすればいいですか?これが私の言うことです。 'Map [String、Any](" foo " - > 1).getAs [Int](" foo ")'は 'None'を返します。 – aa8y

+0

ああ、私は、 'AnyVal'型と' ClassTag'のunapplyでいくつかの変わったセマンティクスがあると思います。私はこれを解決するためにいくつかの掘り起こしをしなければならないでしょう。 – Dylan

関連する問題