如何在scala中覆盖别名类型的等于

时间:2019-04-08 17:31:40

标签: scala override equals

我正在使用如下类型的别名:

trait IPAddress
object IPAddr {
  type IP = Array[Byte] with IPAddress
  type IPv4 <: IP
  type IPv6 <: IP
}

在这里,我想为类型equals覆盖IP方法。怎么办?

3 个答案:

答案 0 :(得分:3)

以下解决方案是通过扩展方法===完成的:

  implicit class IPOps(ip: IP) {
    def ===(other: IP): Boolean = ip.sameElements(other)
  }

  trait IPAddress
  object IPAddr {
    type IP = Array[Byte] with IPAddress
    type IPv4 <: IP
    type IPv6 <: IP
  }

  val ip1 = InetAddress.getByName("1.2.3.4").getAddress.asInstanceOf[IP]
  val ip2 = InetAddress.getByName("1.2.3.4").getAddress.asInstanceOf[IP]
  println(ip1 === ip2) // true

答案 1 :(得分:0)

我真的很惊讶像这样的演员。它不应该:ArrayIP是两种截然不同的类型,您不应将它们转换为另一种。此外,Array也是最终的,您不能对其进行子类化。

我尝试使用此“功能”,并发现对其添加更多详细信息(如添加自类型,如此处的答案之一所示),会使(2.11)编译器崩溃……

此外,一般来说,强制转换很糟糕,因为它绕过了编译时类型检查。

不要这样做。相反,只需创建一个包装器类:

case class IPAddress(bytes: Array[Byte]) {
  override def equals(other: Any) = other match {
    case IPAddress(b) => b.sameElements(bytes)
    case _ => false
  }
}

更好的是,也忘记了包装器,只需使用InetAddress而不是IP。您随时可以根据需要使用.getAddress从中获取字节。

答案 2 :(得分:0)

此构造的要点是IP在运行时准确地由Array[Byte]表示,并且即使在值类不能的情况下也避免装箱/拆箱。

这自然意味着它比值类具有更多个限制,并且您已经无法为其覆盖equals

  

C may not define concrete equals or hashCode methods.

您在这里也不能这样做。您只需要给比较方法起一个不同的名称即可,例如Alexey Novakov的答案。

请注意,从技术上讲,asInstanceOf强制转换为shouldn't work,您应该使用细化类型,例如

type IP = Array[Byte] { type T = IPAddress }