隐式 class 用于覆盖 String.toBoolean

Implicit class for overriding String.toBoolean

我尝试遵循 this 的回答,但没有帮助。这是我的实现。

implicit class MyString(s: String) {
  override def toBoolean = s.trim.toLowerCase match {
    case "true" | "t" | "1" => true
    case _ => false
  }
}

我得到的错误是:

[error]  found   : s.type (with underlying type String)
[error]  required: ?{def toBoolean: ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
[error]  and method MyString in trait ImplicitsStartingWithS of type (s: String)foo.MyString
[error]  are possible conversion functions from s.type to ?{def toBoolean: ?}
[error]           case Some(s) => s.toBoolean
[error]                           ^

我似乎找不到代码有什么问题。

除了 toBoolean 没有覆盖任何内容之外,您的实现没有问题。但是,正如编译器错误所指示的那样,您的方法名称与 Predef 中自动导入的 StringOps class 中的 toBoolean 方法冲突。因此,可以应用的隐式转换不止一种,编译器无法决定使用哪一种。这就是错误表明存在歧义的原因。解决方案是以不同的方式命名您的方法,因此以下应该有效。

implicit class MyString(s: String) {
  def toBooleanAlt = s.trim.toLowerCase match {
    case "true" | "t" | "1" => true
    case _ => false
  }
}

首先,请注意隐式转换不能覆盖正在转换的类型中的方法:如果存在这样的方法,编译器根本不会寻找隐式!有一个名为 Scala-Virtualized 的 Scala 分支确实允许这样做(你会定义一个方法 infix_toBoolean(x: String)),但我建议不要将其用于一般用途:如果没有此功能你就活不下去,请检查它出。

在这种情况下,正如@moem 的回答所说,toBoolean 实际上并未在 String 上定义。作为简单地为您的 toBoolean 指定不同名称的替代方法,您还可以通过使用此名称定义其他内容来在 class 中显式隐藏 augmentStringdef augmentString = ???

class MyString(s: String) {
  def toBoolean = s.trim.toLowerCase match {
    case "true" | "t" | "1" => true
    case _ => false
  }
}

implicit def augmentString(s: String) = new MyString(s)

当然,这也会丢失此隐式提供的所有其他方法,但您可以在 MyString 中提供它们(例如,通过扩展 StringOps)。