代码之家  ›  专栏  ›  技术社区  ›  Synesso

避免scala中的隐式def歧义

  •  15
  • Synesso  · 技术社区  · 15 年前

    我正在尝试创建从任何类型(比如int)到字符串的隐式转换…

    隐式转换为字符串意味着RichString方法(如Reverse)不可用。

    implicit def intToString(i: Int) = String.valueOf(i)
    100.toCharArray  // => Array[Char] = Array(1, 0, 0)
    100.reverse // => error: value reverse is not a member of Int
    100.length // => 3
    

    隐式转换为richstring意味着字符串方法(如tochararray)不可用

    implicit def intToRichString(i: Int) = new RichString(String.valueOf(i))
    100.reverse // => "001"
    100.toCharArray  // => error: value toCharArray is not a member of Int
    100.length // => 3
    

    使用两种隐式转换意味着重复的方法(如长度)不明确。

    implicit def intToString(i: Int) = String.valueOf(i)
    implicit def intToRichString(i: Int) = new RichString(String.valueOf(i))
    100.toCharArray  // => Array[Char] = Array(1, 0, 0)
    100.reverse // => "001"
    100.length // => both method intToString in object $iw of type 
       // (Int)java.lang.String and method intToRichString in object
       // $iw of type (Int)scala.runtime.RichString are possible 
       // conversion functions from Int to ?{val length: ?}
    

    那么,是否可以隐式转换为字符串并仍然支持所有字符串和richstring方法?

    6 回复  |  直到 9 年前
        1
  •  2
  •   Mitch Blevins    15 年前

    要么创建一个巨大的代理类,要么吸收它并要求客户机消除它的歧义:

    100.asInstanceof[string].长度

        2
  •  5
  •   Richard Dallaway    15 年前

    我没有解决方案,但会说原因 RichString 方法在您的 intToString 隐式是scala不链接隐式调用(参见21.2“隐式规则”中的 scala编程 )

    如果你介绍一个中间人 String ,scala将使隐式转换为 富字符串 (该隐式定义在 Predef.scala )

    例如。,

    $ scala
    Welcome to Scala version 2.7.5.final [...].
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> implicit def intToString(i: Int) = String.valueOf(i)
    intToString: (Int)java.lang.String
    
    scala> val i = 100
    i: Int = 100
    
    scala> val s: String = i
    s: String = 100
    
    scala> s.reverse
    res1: scala.runtime.RichString = 001
    
        3
  •  5
  •   Francois G    13 年前

    从scala 2.8开始,这已经得到了改进。按照 this paper (续) 避免模棱两可 )以下内容:

    以前,最特殊的重载方法或隐式转换 将仅基于方法参数类型进行选择。有一个 附加条款,说明最特殊的方法不能 拒绝在任何其他选择的适当超类。这个 在scala 2.8中,方案已被以下更为宽松的方案所取代: 当比较两种不同的过载适用替代方案时 方法或隐式的,每个方法都有一个点 特殊的论点,以及在适当的 子类。如果一个选择的数字更大,它就会战胜另一个选择。 这两个比较中的点。 这尤其意味着如果 备选方案具有相同的参数类型,在 子类获胜。

    that other paper (§6.5)例如。

        4
  •  2
  •   Kim Stebel    15 年前

    我看到的唯一选项是创建一个新的字符串包装类mystring,并让它调用在不明确的情况下要调用的任何方法。然后您可以定义到mystring的隐式转换,以及从mystring到string和richstring的两个隐式转换,以防需要将其传递给库函数。

        5
  •  2
  •   Régis Jean-Gilles    9 年前

    接受的解决方案(由Mitch Blevins发布)永远不会起作用:下推 Int String 使用 asInstanceOf 总是会失败。

    您的问题的一个解决方案是添加从任何字符串可转换类型到 RichString (或更确切地说, StringOps 现在它的名字是:

    implicit def stringLikeToRichString[T](x: T)(implicit conv: T => String) = new collection.immutable.StringOps(conv(x))
    

    然后像前面一样定义到字符串的转换:

    scala> implicit def intToString(i: Int) = String.valueOf(i)
    warning: there was one feature warning; re-run with -feature for details
    intToString: (i: Int)String
    
    scala> 100.toCharArray
    res0: Array[Char] = Array(1, 0, 0)
    
    scala> 100.reverse
    res1: String = 001
    
    scala> 100.length
    res2: Int = 3
    
        6
  •  1
  •   oxbow_lakes    15 年前

    我很困惑:你不能用吗 .toString 在任何类型上都可以避免隐式转换?