我想通过添加一些辅助方法为Scala中的自然数创建一个"pimp my type".
我的第一次尝试是创建一个for Int和one for Long(后来BigInt也许一个)
implicit class SuperInt(n:Int) {
def square = n * n
def pow(m: Int) = math.pow(n,m)
def **(m: Int) = pow(m)
def sqrt = math.sqrt(n)
def isEven = dividesBy(2)
def isOdd = !isEven
def dividesBy(m:Int) = n % m == 0
}
implicit class SuperLong(n:Long) {
def square = n * n
def pow(m: Int) = math.pow(n,m)
def **(m: Int) = pow(m)
def sqrt = math.sqrt(n)
def isEven = dividesBy(2)
def isOdd = !isEven
def dividesBy(m:Int) = n % m == 0
}
Run Code Online (Sandbox Code Playgroud)
当然完全相同的代码,不是太干,也不"感觉"正确.
所以我的问题是 - 什么是(惯用的)Scala方式一次为Long,Int和BigInt做这个?
ps这是我到目前为止所尝试的,它有点工作,但我很确定它不是惯用的,并且有很多问题.
以下是关于"类型类"的一点阅读结果(我仍然没有完全感觉到我100%理解)所以这就是结果(如果你的眼睛受伤了,请原谅我,我比较新斯卡拉)
implicit class SuperNumber[A : Numeric](i: A) {
import Numeric.Implicits._
def squared: A = i * i
def pow(m: Int) = math.pow(i.toDouble(),m)
def **(m: Int) = pow(m)
def sqrt = math.sqrt(i.toDouble())
def isEven = dividesBy(2)
def isOdd = !isEven
def dividesBy(m:Int) = {
i match {
case n @ (_:Int | _:Long) => n.toLong() % m == 0
case other => {
val asDouble = other.toDouble()
val asLong = other.toLong()
if (asDouble == asLong) {
asLong % m == 0
} else {
false
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(我为非Int和Long添加了"支持",因为它似乎并不太难)
你有什么看起来非常接近.一些评论:
你想要的类型是Integral,而不是Numeric.
不是将上下文绑定为[A: Integral],而是在构造函数上放置一个隐式参数,因此您可以mkNumericOps从该对象导入:
implicit class SuperNumber[A](i: A)(implicit integral: Integral[A]) {
import integral._
Run Code Online (Sandbox Code Playgroud)