繁体   English   中英

Scala:覆盖等于值类

[英]Scala: Overriding equals for value classes

为了在我们的代码库中获得更多的类型安全性,我们已开始用类型安全值类替换通用Strings,Ints等,但是我正在努力使它们方便地与==运算符和文字一起使用。 希望有人可以帮助我。

我们的值类的定义和使用方式如下:

case class Name(value: String) extends AnyVal {}
object Name { implicit def to(something:String): Name = Name(something) // convenience }

case class Address(value: String) extends AnyVal {}
object Address { implicit def to(something:String): Address = Address(something) // convenience }

case class Person(name: Name, address: Address) {
  def move(newAddress: Address) = copy(address=newAddress)
}
val somebody = Person("Pete", "Street 1")

somebody.move(Address("Street 2")) // allowed
somebody.move(somebody.name) // not allowed, which is exactly what we want
somebody.move("Street 2") // allowed by convenience

现在,我希望他们能够“自然地”比较其内在value

Name("Pete") == "Pete" // should be true, but evaluates to False 

我可以通过覆盖equals来解决此问题:

case class Name(value: String) extends AnyVal {
  override def equals(other: Any) = 
    if (other.isInstanceOf[Name])
      other.asInstanceOf[Name].value == this.value
    else if (other.isInstanceOf[String])
      other == this.value
    else
      false
}

Name("Pete") == "Pete" // now evaluates to true

但是,此解决方案不是对称的:

"Pete" == Name("Pete") // evaluates to false, because it is using String.equals

我不知道该如何解决。 甚至没有声明从Name到String的隐式转换会有所帮助(而且我更希望不要有这种东西)。 可以做我想做的事吗?

编辑:我可能对此不清楚,但是我并不是真正在寻求有关软件开发的建议。 这是一个技术问题:能否在Scala中完成?

我有做我描述的原因,但是可悲的是,它们与成千上万的Scala代码行有关,无法在简短的堆栈溢出问题中传达。

我认为,您应该只是摆脱convenience隐式。 他们达到了目的:

 val john = Person("Street 1", "John") // mixed up order
 john.move("Pete") // Yup, I can "move" to a name ... 

现在,约翰(John)是一个名为“街道1”的人,住在地址“皮特”。 在定义所有值类的麻烦之后,这不是您要允许的。

我不认为==可以在这种情况下工作。 您可能要做的是定义一个不同的比较操作。

case class Name(value: String) extends AnyVal {
  def is(n: Name): Boolean = value == n.value
}

您还必须扩大隐式转换器的范围,以便可以为这些转换访问它。

implicit def toName(something:String): Name = Name(something) // not in object

现在这有效。

val somebody = Person("Pete", "Street 1")
somebody.move(Address("Street 2")) // allowed
somebody.move("Street 2") // allowed by convenience
somebody.name is "Pete"   // true
"Pete" is somebody.name   // true

暂无
暂无

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

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