【问题标题】:How to unimport String "+" operator in Scala?如何在 Scala 中取消导入字符串“+”运算符?
【发布时间】:2026-01-22 06:50:01
【问题描述】:

我正在编写一个 DSL,其中“+”运算符是严格数字的,就像其他一些流行的语言一样。它很接近,但字符串“+”运算符搞乱了我的隐式转换。取消导入 String 类的运算符的语法是什么?

只是为了更清楚,而不是这样:

scala> var x = "2" + 3; x:java.lang.String = 23

我想得到 x: Int = 5

我想我只需要两件事就可以做到这一点:

  • 从字符串中删除(在我的范围内取消导入)“+”的定义
  • 定义 String 到 Int 的隐式转换

我被困在第一步。

谢谢

【问题讨论】:

  • 我想“import scala.Predef.{any2stringadd => _}”会起作用。但事实并非如此。一定是我错过了什么。
  • any2stringadd 用于左侧不支持 + 运算符的情况,但右侧是字符串。 (要查看实际情况,请运行 scala -Xprint:typer 并执行 new Object + "ZZZZZ")相比之下,"ZZZZZ" + new Object 可以使用已在 String 上定义的 + 运算符,因此不使用 any2stringadd

标签: scala scala-2.8


【解决方案1】:

根据Scala spec 的第12.3.1 节,String+ 方法被编译器特殊处理。我不确定,但我认为这意味着您不能“取消导入”它,这很遗憾,因为它确实破坏了类型系统(很像相关的 toString 方法)。

您能否为 DSL 中的运算符使用不同的名称,例如 ++&

【讨论】:

  • + 方法被编译器特殊处理的事实与它是否可以导入或不导入无关。该语言应该是非常正交的,并且在语义上将所有类方法视为相同,无论它们是由编译器合成还是由运行时库提供。
  • 如果+ 确实在String 类上明确指定,我会同意您所说的,但规范仅暗示这一点,IMO 可以解释为存在隐式转换(被编译到编译器中,因此不能“取消导入”)到某种类型(例如,StringAdd),这允许客户端将String 视为使用+ 方法定义的。我很高兴在这里被证明是错误的,但即使通过String(和RichString)的运行时反射,我也找不到+(即$plus)方法。
  • 谢谢,听起来像是“编译器魔法”的另一种情况,它实际上打破了正交性并与其他语言功能和库产生了意想不到的交互。
  • 是的,我不知道为什么它不能以与Predef.any2stringadd 相同的方式实现,例如Predef.string2stringadd:String => StringAdd
  • 在现代 scala 中,可以取消导入 String 并使用自定义插值器来生成自定义类型。目前不可能为字符串文字语法提供自定义的“空”插值器。
【解决方案2】:

字符串的 + 方法是 String 类的一个方法(因此在 each 字符串对象上),因此它不能被取消导入。

【讨论】:

    【解决方案3】:

    您不能取消导入它,但您可以使用 +: 并在 int 类上定义它。最好是这样写:"2".toInt + 3。

    【讨论】: