是否有可能在Scala中定义构造函数局部变量?
以下代码来自Martin Odersky等人编写的Scala书籍。它定义了一个合理的类型:是否有可能在Scala中定义构造函数局部变量?
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n/g
val denom = d/g
...
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
这里的值g只在隐式构造函数初始化字段numer和denom时使用。假设程序员知道它不会在其他地方使用。在上述情况下,在构造Rational对象之后仍然可以访问它。这意味着它将占用空间,因为它是一个私有字段,而不是构造函数的局部变量。
我的问题是如何更改此代码,以便g
仅在施工时使用,然后丢弃?
在这种情况下,这样的事情呢?
class Rational(n: Int, d: Int) {
require(d != 0)
val (numer, denom) = {
val g = gcd(n.abs, d.abs)
(n/g, d/g)
}
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
编辑:这也创建了拥有一个元组,如通过在编译的类(感谢,阿列克谢)运行javap
一个额外的字段:
public class Rational extends java.lang.Object implements scala.ScalaObject{
private final scala.Tuple2 x$1; // actually unwanted!
private final int numer;
private final int denom;
public int numer();
public int denom();
private int gcd(int, int);
public Rational(int, int);
}
在其他情况下,我有时使用locally
块来避免每个val
转化为一个字段:
class A {
locally {
val value1 = // ...
val value2 = // ...
}
}
谢谢你可能是最好的解决方案。我还了解了“本地”区块,所以再次感谢。 – ciuncan 2012-01-12 22:31:20
我是否也可以使用在本地块外定义的值或变量,就在该类体中?或者他们只是本地阻止? – ciuncan 2012-01-12 22:35:13
@ciuncan在代码块中声明的任何内容(即用大括号分隔)只能在该块内访问。 “本地”仅仅是避免分号推理问题(不是关键字)的一种便利方法,所以不能改变它。有关'本地“的信息,请参阅http://*.com/questions/3237727/what-does-predef-locally-do-and-how-is-it-different-from-predef-identity。 – 2012-01-13 01:11:44
这是Scala中那些“恶心点”之一。想象一下,如果给定的构造函数对象仅用于提取一些任意的信息:即使只需要一小部分信息,永久使用它也会使其不适合回收。我认为有一个“课前体”的语法,但我不记得它是什么。 – 2012-01-12 22:15:40
@pst感谢您的快速编辑,我在此期间正在这么做。你的看起来好多了。 :) – ciuncan 2012-01-12 22:16:20
如果任何人有任何关于pst提到的“pre-class body”语法的链接,我很乐意听到它。 – 2012-01-13 01:16:30