[英]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
方法可能很困难或不可能-考虑一下您在尝试比较String
和Object
时已经目睹的不对称性,并查看这篇旧文章以彻底解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.