我正在使用如下类型的别名:
trait IPAddress
object IPAddr {
type IP = Array[Byte] with IPAddress
type IPv4 <: IP
type IPv6 <: IP
}
在这里,我想为类型equals
覆盖IP
方法。怎么办?
答案 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)
我真的很惊讶像这样的演员。它不应该:Array
和IP
是两种截然不同的类型,您不应将它们转换为另一种。此外,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
:
您在这里也不能这样做。您只需要给比较方法起一个不同的名称即可,例如Alexey Novakov的答案。
请注意,从技术上讲,asInstanceOf
强制转换为shouldn't work,您应该使用细化类型,例如
type IP = Array[Byte] { type T = IPAddress }