我正在写一个DSL,我最终希望能够拥有自己的字符串类型,我可以在这里做一些事情,比如
var s:BString = "123"
if ("123" == s) ...
以及
var d:Double = s + 5.0
我基本上使用隐式转换以及5.0 + s
我也有= =通过覆盖我的'BString'类中的equals方法来工作,其中第一个参数(左侧)是一个BString。
问题是以某种方式覆盖Java String equals。我看了一下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
}
}
答案 0 :(得分:0)
尽管我不喜欢实现语言行为,比如在双打中添加字符串(反之亦然),这就是你可以做的:
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
的定义,使得它在其参数的运行时类型上匹配模式,并且我还给了typer一个暗示“1.1”真的写BString
撰写("1.1": BString)
。
编辑:另请注意,您实际上不需要def +(d: Double)
方法。
答案 1 :(得分:0)
String
是JDK中的最后一个类,原因很多 - 如果你被允许使用它的equals
方法,你基本上可以破坏JVM的整个安全模型! (有关详细原因,请参阅this question。)
既然如此,你能在DSL上做的最好的就是引入一个未定义String
的新运算符,例如===
,并确保你有隐式转换可用于String
到BString
:
class BString(val string: String) {
def ===(other: BString) = TODO
}
object BString {
implicit def string2BString(x: String) = new BString(x)
}
你也可以考虑让你的BString
课程最终成绩。面对继承,编写正确的equals
方法可能很困难或不可能 - 考虑一下您在尝试比较String
和Object
时已经目睹的不对称性,并查看{{ 3}}彻底解决问题。