15

我正在尝试创建从任何类型(例如,Int)到字符串的隐式转换...

隐式转换为 String 意味着 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: ?}

那么,是否可以隐式转换为 String 并且仍然支持所有 String 和 RichString 方法?

4

6 回答 6

5

我没有解决方案,但会评论说,在隐式RichString之后方法不可用的原因intToString是 Scala 没有链接隐式调用(请参阅Programming in Scala中的 21.2“Rules forimplicits” )。

如果你引入一个Stringmiddle ,Scala 会将隐式转换为 a RichString(隐式在 中定义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
于 2009-08-27T09:07:52.700 回答
5

从 Scala 2.8 开始,这一点得到了改进。根据本文(§避免歧义):

以前,最具体的重载方法或隐式转换将仅根据方法的参数类型来选择。有一个附加条款说,最具体的方法不能在任何其他替代方案的适当超类中定义。该方案在 Scala 2.8 中已被以下更自由的方案所取代:当比较重载方法或隐式方法的两种不同的适用替代方案时,每个方法因具有更具体的参数而得一分,因在适当的子类。如果在这两个比较中获得更多分数,则替代方案“胜过”另一个。这尤其意味着,如果备选方案具有相同的参数类型,则在子类中定义的参数类型获胜。

有关示例,请参见另一篇论文(第 6.5 节)。

于 2011-01-16T12:53:03.080 回答
2

我看到的唯一选择是创建一个新的 String Wrapper 类 MyString 并让它调用您想要在模棱两可的情况下调用的任何方法。然后,您可以定义到 MyString 的隐式转换以及从 MyString 到 String 和 RichString 的两个隐式转换,以防万一您需要将其传递给库函数。

于 2009-08-27T06:37:10.663 回答
2

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

100.asInstanceOf[字符串].length

于 2009-08-27T08:57:50.927 回答
2

接受的解决方案(由 Mitch Blevins 发布)永远不会奏效:向下转换IntStringusingasInstanceOf总是会失败。

您的问题的一种解决方案是添加从任何可转换字符串的类型到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
于 2015-05-06T08:18:29.547 回答
1

我很困惑:你不能.toString在任何类型上使用,从而避免需要隐式转换吗?

于 2009-08-27T07:56:25.683 回答