2013-07-03 106 views
1

有人可以告诉我为什么,如下所示,当创建KeyVal对象时隐式转换工作,但在作为KeyVal的Map中创建键时不起作用。使用隐含的scala映射键

谢谢。

object o { 
    case class KeyVal(i: Int) 
    object KeyVal { 
    implicit def strToKeyVal(s:String) = KeyVal(s.toInt) 
    } 
} 

import o._ 

val x : KeyVal = "1" // Works fine to create a KeyVal 

val x : Map[KeyVal, String] = Map("1" -> "One") // Type Mismatch: found (String, String), wants (KeyVal, String) 

回答

3

Scala编译器不是一个全能的东西,它不能解决所有类型的类型错误。它应该如何将(String, String)元组转换为(KeyVal, String)元组,以及为什么不将其转换为(String, KeyVal)(KeyVal, KeyVal)。您的隐式转换会将String转换为KeyVal,但不会将(String, String)转换为KeyVal。如果添加此隐式转换为同伴对象:

implicit def strToKeyVal(s: (String, String)): (KeyVal, String) = (KeyVal(s._1.toInt), s._2) 

一切都会正常工作

+0

感谢。我猜想它知道只有Tuple的第一个成员需要转换太多。然而,我不认为这是不合理的,因为它应该知道Tuple的第一个成员是一个KeyVal,因为这个值是一个Map [KeyVal,String] – user1922871

3

这只是一个时机问题。在考虑Map的类型时,不再有String,而是(String, String)元组。发生这种情况是因为->是首先应用的运算符,然后其结果返回Map

如果您避免使用运营商,它的工作原理:

val x : Map[KeyVal, String] = Map(("1", "One")) 
+0

这很有道理。我想出的另一种方法是使用隐式类KeyVal(s:String),该类有一个方法:def holds(contents:String)=(this - > contents)然后映射可以定义为Map [KeyVal,String ] =地图(“1”包含“一”)。这对我来说很有用,因为KeyVal实际上是放在一个盘子上的,所以它说那个井有一些内容。感谢所有的好的答案。 – user1922871