【问题标题】:Type mismatch error when invoking method in Scala在 Scala 中调用方法时出现类型不匹配错误
【发布时间】:2016-04-04 00:28:47
【问题描述】:

我有一个基类,以及它的子类 MString 和 MInt。

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)

使用此映射,我尝试使用字符串作为键来检索对象并调用编码方法。

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

但是,我遇到了类型不匹配错误:

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").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)
}

有解决这个问题的办法吗?

【问题讨论】:

  • 您正在从 Map[String, Base[_]] 检索值。那将是Base[_](类型未知)。编译器无法知道它是MInt 还是MString

标签: scala generics types


【解决方案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

我们可以通过 match/case 来简化编码函数:

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")
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多