scala,初始化抽象vals
发布时间:2020-12-16 08:45:23 所属栏目:安全 来源:网络整理
导读:“ Scala编程,第三版,Martin Odersky”一书在第449页给出了这个例子: trait RationalTrait { val numerArg: Int val denomArg: Int require(denomArg != 0) private val g = gcd(numerArg,denomArg) val numer = numerArg / g val denom = denomArg / g pri
“
Scala编程,第三版,Martin Odersky”一书在第449页给出了这个例子:
trait RationalTrait { val numerArg: Int val denomArg: Int require(denomArg != 0) private val g = gcd(numerArg,denomArg) val numer = numerArg / g val denom = denomArg / g private def gcd(a: Int,b: Int): Int = if (b == 0) a else gcd(b,a % b) override def toString = numer + "/" + denom } 然后它解释了以下代码失败,因为trait在匿名类之前被初始化,因此,denomArg仍为0. new RationalTrait { val numerArg = 4 val denomArg = 24 } 它提供了两种解决方案.一种解决方案是使用预先初始化的字段: new { val numerArg = 4 val denomArg = 24 } with RationalTrait 第二种解决方案是修改特性以使用延迟值,如下所示: trait LazyRationalTrait { val numerArg: Int val denomArg: Int lazy val numer = numerArg / g lazy val denom = denomArg / g override def toString = numer + "/" + denom private lazy val g = { require(denomArg != 0) gcd(numerArg,denomArg) } private def gcd(a: Int,a % b) } new LazyRationalTrait { lazy val numerArg = 4 lazy val denomArg = 24 } 但是,这个更简单的解决方案也有效.我想知道为什么他们没有提到这个解决方案.这有什么缺点吗? new RationalTrait { lazy val numerArg = 4 lazy val denomArg = 24 } 解决方法
我认为你的解决方案与第二个选项相比更加一致(在Scala编程的第453页提到,3d ed.):
trait A { val x: Int lazy val y: Int = x val z: Int = y } new A { val x = 1 }.y // ==0 ?!!! new A { val x = 1 }.z // ==0 ?!!! VS trait A { val x: Int val y: Int = x val z: Int = y } new A { lazy val x = 1 }.y // ==1 new A { lazy val x = 1 }.z // ==1 至少我不需要记住懒惰的val不能用在基类中的非惰性构造中.查看字节码我没有看到你的方法有任何明显的问题,因为在后一种情况下,x被有效地定义为def,所以它在基类中初始化时已经存在. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |