2016-04-04 17 views
1

私は基底クラスとそれからサブクラスのMStringとMIntを持っています。Scalaでメソッドを呼び出すときに型の不一致エラーが発生しました

abstract class Base[T](val name:java.lang.String = "") { 
    def encode(value:T) : Array[Byte] 
} 

class MString extends Base[String](name = "string") { 
    def encode(value:String) = { 
     Array[Byte](10,20) 
    } 
} 

class MInt extends Base[Int](name = "int") { 
    def encode(value:Int) = { 
     Array[Byte](100,11) 
    } 
} 

私はクラス名とそのインスタンスを結ぶマップを持っています。このマップでは

val m = Map[String, Base[_]]("string" -> new MString, "int" -> new MInt) 

、私はオブジェクトを取得し、encodeメソッドを呼び出すためのキーとして文字列を使用しようとしていました。

error: type mismatch; 
found : String("A") 
required: _$1 where type _$1 
    println(m("string").encode("A")) 
          ^
/Users/smcho/code/codetemplate/_pl/scala/_learn/exploration/2016/04/03. type_inference.scala:25: error: type mismatch; 
found : Int(10) 
required: _$1 where type _$1 
    println(m("int").encode(10)) 

ソリューションはasInstanceOfに特化することである。

println(m("string").encode("A")) 
println(m("int").encode(10)) 

しかし、私は、型の不一致エラーを得ました。

println(m("string").asInstanceOf[MString].encode("A")) 
println(m("int").asInstanceOf[MInt].encode(10)) 

このエラーはなぜですか? Scalaコンパイラは、そのパラメータの型からメソッドを呼び出すほどスマートではありません(たとえば、 "A" - > encode(String)および10 - > encode(Int))?

私は別のマップを持っているので、これは私のコードの問題で、エンコーディング結果を取得するために使用されます。

val m2 = Map[String, Any]("int"->10, "string"->"A") 

m2 foreach { 
case (key, value) => m(key).encode(value) 
} 

この問題を解決するにはどうすればよいですか?

+1

あなたは '地図[文字列、ベースから値を取得しています[_]] '。これは 'Base [_]'(型が不明)です。コンパイラは 'MInt'か' MString'かどうかを知ることができません。 – Thilo

答えて

-1

おそらく、私はBaseクラスから継承する各タイプを特化する以外に選択肢はありません。

def encode(input:String, value:Any, m:Map[String, Base[_]]) = { 
    if (input.startsWith("string")) 
     m("string").asInstanceOf[MString].encode(value.asInstanceOf[String]) 
    else if (input.startsWith("int")) 
     m("int").asInstanceOf[MInt].encode(value.asInstanceOf[Int]) 
    else 
     throw new Exception("Not supported type") 
} 

val m2 = Map[String, Any]("int"->10, "string"->"A") 

m2 foreach { 
    case (key, value) => println(encode(key, value, m).mkString(":")) 
} 

表示されます。このコードを実行する:

100:11 
10:20 

我々は一致/ケースでエンコード機能簡単にすることができます。

def encode2(input:String, value:Any, m:Map[String, Base[_]]) = {   
    input match { 
     case input if input.startsWith("string") 
      => m("string").asInstanceOf[MString].encode(value.asInstanceOf[String]) 
     case input if input.startsWith("int") 
      => m("int").asInstanceOf[MInt].encode(value.asInstanceOf[Int]) 
     case _ => throw new Exception("Not supported type") 
    } 
} 
関連する問題