避免 Scala 中隐式 def 歧义
我正在尝试创建从任何类型(例如 Int)到 String 的隐式转换...
到 String 的隐式转换意味着 RichString 方法(如反向)不可用。
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 的隐式转换意味着 String 方法(如 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
使用这两种隐式转换意味着重复的方法(如 length)不明确。
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 方法?
I am trying to create an implicit conversion from any type (say, Int) to a String...
An implicit conversion to String means RichString methods (like reverse) are not available.
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
An implicit conversion to RichString means String methods (like toCharArray) are not available
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
Using both implicit conversions means duplicated methods (like length) are ambiguous.
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: ?}
So, is it possible to implicitly convert to String and still support all String and RichString methods?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我没有解决方案,但会评论说,在
intToString
隐式之后RichString
方法不可用的原因是 Scala 不会链接隐式调用(请参阅 21.2“规则”)对于隐式”Scala 编程)。如果引入中间
String
,Scala 将隐式转换为RichString
(该隐式转换在Predef.scala
中定义)。例如,
I don't have a solution, but will comment that the reason
RichString
methods are not available after yourintToString
implicit is that Scala does not chain implicit calls (see 21.2 "Rules for implicits" in Programming in Scala).If you introduce an intermediate
String
, Scala will make the implict converstion to aRichString
(that implicit is defined inPredef.scala
).E.g.,
从 Scala 2.8 开始,这一点得到了改进。根据 本文(§避免歧义):
请参阅另一篇论文(§6.5) )为例。
As of Scala 2.8, this has been improved. As per this paper (§ Avoiding Ambiguities) :
See that other paper (§6.5) for an example.
要么创建一个巨大的代理类,要么将其吸收并要求客户端消除歧义:
100.asInstanceOf[String].length
Either make a huge proxy class, or suck it up and require the client to disambiguate it:
100.asInstanceOf[String].length
我看到的唯一选择是创建一个新的字符串包装类 MyString 并让它调用您想要在不明确的情况下调用的任何方法。然后,您可以定义到 MyString 的隐式转换以及从 MyString 到 String 和 RichString 的两个隐式转换,以防万一您需要将其传递给库函数。
The only option I see is to create a new String Wrapper class MyString and let that call whatever method you want to be called in the ambiguous case. Then you could define implicit conversions to MyString and two implicit conversions from MyString to String and RichString, just in case you need to pass it to a library function.
接受的解决方案(由 Mitch Blevins 发布)永远不会起作用:使用
asInstanceOf
将Int
向下转换为String
将始终失败。解决您的问题的一种方法是添加从任何字符串可转换类型到
RichString
的转换(或者更确切地说,添加到StringOps
的转换,因为它现在被命名为):然后定义您的转换( s) 像以前一样串起来:
The accepted solution (posted by Mitch Blevins) will never work: downcasting
Int
toString
usingasInstanceOf
will always fail.One solution to your problem is to add a conversion from any String-convertible type to
RichString
(or rather, toStringOps
as it is now named):Then define your conversion(s) to string as before:
我很困惑:你不能在任何类型上使用
.toString
从而避免隐式转换的需要吗?I'm confused: can't you use
.toString
on any type anyway thus avoiding the need for implicit conversions?