简体   繁体   English

在 Scala 中调用方法时出现类型不匹配错误

[英]Type mismatch error when invoking method in Scala

I have a base class, and subclasses MString and MInt from it.我有一个基类,并从中继承了 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)
    }
}

I have a map that connects the class name and an instance of it.我有一个连接类名和它的实例的映射。

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

With this map, I was trying to use a string as a key to retrieve the object and invoke the encode method.使用此映射,我尝试使用字符串作为键来检索对象并调用 encode 方法。

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

However, I got type mismatch errors:但是,我遇到了类型不匹配错误:

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

The solution is to specialize with asInstanceOf .解决方案是专门使用asInstanceOf

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

Why is this error?为什么会出现这个错误? Isn't Scala compiler smart enough to invoke the method from the type of its parameter, for example ("A" -> encode(String) and 10 -> encode(Int))? Scala 编译器是否足够聪明,无法从其参数的类型调用该方法,例如 ("A" -> encode(String) 和 10 -> encode(Int))?

This is an issue for my code, as I have another map, and it is used to get the encoding results.这是我的代码的问题,因为我有另一张地图,它用于获取编码结果。

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

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

Any idea to solve this issue?有什么想法可以解决这个问题吗?

Maybe, I have no choice but to specialize each type that inherits from the Base class.也许,我别无选择,只能专门化从 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(":"))
}

Running this code will show:运行此代码将显示:

100:11
10:20

We can make the encode function simpler with match/case:我们可以使用 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")
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM