我正在使用如下所示的类型别名:
trait IPAddress
object IPAddr {
type IP = Array[Byte] with IPAddress
type IPv4 <: IP
type IPv6 <: IP
}
在这里,我想覆盖类型为equals
的IP
方法。怎么办?
下面的解决方案是使用扩展方法===
完成的:
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
我真的很惊讶像这样的演员工作。它不应该: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
从中获取字节数。
这个结构的要点是IP
在运行时由Array[Byte]
完全表示,并且即使在值类不能的情况下也要避免装箱/拆箱。
这自然意味着它比值类有更多的限制,你已经不能为它们覆盖equals
:
你也不能在这里做到。你只需要给你的比较方法一个不同的名字,就像在Alexey Novakov的回答中那样。
请注意,从技术上讲,asInstanceOf
施放shouldn't work并且您应该使用细化类型,例如
type IP = Array[Byte] { type T = IPAddress }