繁体   English   中英

覆盖字符串等于

[英]Overriding String equals

我正在写一个DSL,最终我希望能够拥有自己的字符串类型,在其中我可以做类似的事情

var s:BString = "123"
if ("123" == s) ...

并且

var d:Double = s + 5.0

我还有一些基本工作,以及5.0 + s的隐式转换

我还通过覆盖我的'BString'类中的equals方法以一种方式工作==,其中第一个参数(左侧)是BString。

问题在于以某种方式覆盖了Java字符串等于。 我看了一下String.equals()源代码,equals方法使用了一个Java对象,我似乎无法使用它进行隐式转换。 然后,其中的equals方法将对象转换为字符串,因此我认为,除非我有(final)String的子类,否则我是SOL。

还有其他方法吗? 有想法吗?

class BString(val string: String) {
    override def toString() = string
    def toDouble:Double = string.toDouble
    def +(bs:BString) = string.toDouble + bs.toDouble
    def +(d:Double) = string.toDouble + d
    override def equals(x$1:Any):Boolean = string == x$1.toString
} 

object Test {

  implicit def string2BString(x:String)  = new BString(x)
  implicit def double2BString(x:Double)  = new BString(x.toString)
  implicit def bString2Object(x:BString) = { // never being reached
    println("OO");
    x.asInstanceOf[Object]
  } 

  def main(args: Array[String]) {

    var y:BString = "1.1"
    println(y + 1.1)        //2.2
    println(1.2 + y)        //2.3
    println("1.1" == y)     // false :-(
    println("1.1" equals y) // false :-(
    println("1.1" equals bString2Object(y)) // also false
    println(y == "1.1")     // true
  }

}

尽管我不喜欢实现将字符串添加到双打(反之亦然)之类的语言行为,但是您可以执行以下操作:

import scala.language.implicitConversions

class BString(val string: String) {
  def toDouble: Double = string.toDouble
  def +(bs: BString): Double = string.toDouble + bs.toDouble
  def +(d: Double): Double = string.toDouble + d
  override def equals(other: Any) = other match {
    case bs: BString => string == bs.string
    case os: String  => string == os
    case _           => false
  }
}

object BString {
  implicit def string2BString(x: String) = new BString(x)
  implicit def double2BString(d: Double) = new BString(d.toString)
}

object Test extends App {
  val y: BString = "1.1"
  println(y + 1.1)                   // 2.2
  println(1.2 + y)                   // 2.3
  println(("1.1": BString) == y)     // true
  println(("1.1": BString) equals y) // true
  println(y == "1.1")                // true
}

如您所见,我已经更改了两个equals的定义,以使其在其参数的运行时类型上与模式匹配,并且通过给定类型提示,“ 1.1”实际上是一个BString ,写法是“ ("1.1": BString)

编辑:还请注意,您实际上不需要def +(d: Double)方法。

出于多种原因, String是JDK中的最终类-基本上,如果允许您使用JVM的equals方法,则可能会损害JVM的整个安全模型! (有关详细原因,请参阅此问题 。)

这样,您将在DSL中做的最好的事情就是引入一个未为String定义的新运算符,例如=== ,并确保您可以将String隐式转换为BString

class BString(val string: String) {
  def ===(other: BString) = TODO
}

object BString {
  implicit def string2BString(x: String) = new BString(x)
}

您也可以考虑将BString类也BString final。 面对继承,编写正确的equals方法可能很困难或不可能-考虑一下您在尝试比较StringObject时已经目睹的不对称性,并查看这篇旧文章以彻底解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM