Stuck创建可隐式转换from /到Int Natgural数字类
问题描述:
我几天前开始玩Scala。 我想要做的是编写一个非常小的代表自然数的类,我希望它可以隐式地转换成Int
。老实说,到目前为止我还没有做很多。下面是代码:Stuck创建可隐式转换from /到Int Natgural数字类
object main {
class Natural(n: Int) {
def isDividerOf(m: Natural): Boolean = m % n == 0
}
implicit def Int(m: Natural): Int = m
implicit def Natural(n: Int): Natural = new Natural(n)
def main(args: Array[String]) ={
println("test")
println(60 isDividerOf 600)
}
}
的代码可以编译,但是当我运行它(无论我作为参数传递给isDividerOf
使用的数字)的程序执行暂停/永远挂在打印后换句话说test
它不会输出任何数据,它不会正常退出。
我在做什么错?
答
您对implicit Natural => Int
的定义负责无限递归;你所写的是等效于下面的(expliciting在你的代码中的隐式转换):
implicit def Int2Nat(m: Natural): Int = Int2Nat(m)
你要代替的是:
implicit def Int2Nat(m: Natural): Int = m.n // Also change n to a val
我的编译代码得到这个信息与,这显示你的代码的内部编译器表示之后它已经typechecked(和所有implicits已经解决):
$ scalac -Xprint:typer so.scala
[[syntax trees at end of typer]] // s.scala
package <empty> {
object main extends scala.AnyRef {
def <init>(): main.type = {
main.super.<init>();
()
};
class Natural extends scala.AnyRef {
<paramaccessor> private[this] val n: Int = _;
<stable> <accessor> <paramaccessor> def n: Int = Natural.this.n;
def <init>(n: Int): main.Natural = {
Natural.super.<init>();
()
};
def isDividerOf(m: main.Natural): Boolean = main.this.Int(m).%(Natural.this.n).==(0)
};
implicit def Int(m: main.Natural): Int = main.this.Int(m);
implicit def Natural(n: Int): main.Natural = new main.this.Natural(n);
def main(args: Array[String]): Unit = {
scala.Predef.println("test");
scala.Predef.println(main.this.Natural(60).isDividerOf(main.this.Natural(600)))
}
}
}
但请不要使用隐式转换。永远。他们是魔鬼。
您可以用Int
扩展方法达到同样的效果:
implicit class isDividerOfOp(i: Int) {
def isDividerOf(other: Int): Boolean = other % i == 0
}
感谢@OlivierBlanvillain。 '''-Xprint:typer'''真的很有帮助,我不知道这件事。你能解释为什么你不建议使用隐式转换吗?因为它们是混淆的来源或者还有其他原因?我真的有一个印象,它在scala中很常见。 – Gonzalez
作为一个初学者,你作为一个初学者被隐藏的转换所困惑,你花时间继续研究这个问题,并问这个问题,IMO是一个相当好的指标,隐含的转换是混淆的一个重要来源。关于这个问题有很多话要说,请打开另一个问题“为什么我不应该在代码中使用隐式转换?” :) – OlivierBlanvillain