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

问题描述 投票:1回答:3

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

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

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

scala override equals
3个回答
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

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从中获取字节数。


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 }
© www.soinside.com 2019 - 2024. All rights reserved.