[英]How do you define a local var/val in the primary constructor in Scala?
[英]In Scala, how do you define a local parameter in the primary constructor of a class?
在Scala中,如何在不是數據成員的類的主構造函數中定義局部參數,例如,僅用於初始化基類中的數據成員?
例如,在下面的代碼中,如何在B
類的主構造函數中正確定義參數b
,以便它只生成臨時本地參數而不是數據成員?
class A(var a: Int)
class B(?b?) extends A(b)
Randall,你的答案解釋了當我引入一個增加屬性a
的方法inc
時Scala編譯器抱怨的原因,但是也改變了類B
構造函數中參數的名稱以匹配類A
構造函數中的參數名稱:
class A(var a: Int)
class B(a: Int) extends A(a) {
def inc(value: Int) { this.a += value }
}
Scala編譯器輸出:
$ scala construct.scala
construct.scala:3: error: reassignment to val
def inc(value: Int) { this.a += value }
^
one error found
Scala抱怨,因為B
類現在必須擁有一個私有的只讀屬性a
因為它引用a
in inc
。 將B(a: Int)
更改為B(var a: Int)
生成不同的編譯器錯誤:
construct.scala:2: error: error overriding variable a in class A of type Int;
variable a needs `override' modifier
class B(var a: Int) extends A(a) {
^
one error found
添加override
也無濟於事:
construct.scala:2: error: error overriding variable a in class A of type Int;
variable a cannot override a mutable variable
class B(override var a: Int) extends A(a) {
^
one error found
如何在B
的主構造函數中的參數中使用與基類A
的主構造函數中定義的屬性相同的名稱?
如果從構造函數參數中刪除“var”或“val”關鍵字,則它不會生成屬性。
但請注意,非var,非val構造函數參數是范圍內的,並且可以在整個類中訪問。 如果在非構造函數代碼中使用一個代碼(即,在方法體中),則生成的類中將存在一個隱藏該構造函數參數的不可見私有字段,就像您將其設置為“private var”或“ private val“構造函數參數。
附錄 (遲到總比沒有好)?
在此代碼中,構造函數參數的引用僅出現在構造函數體中:
class C1(i: Int) {
val iSquared = i * i
val iCubed = iSquared * i
val iEven = i - i % 2
}
...這里的值i
僅在構造函數的執行期間存在。
但是,在下面的代碼中,因為構造函數參數在方法體中引用 - 它不是構造函數體的一部分 - 構造函數參數必須復制到生成的類的(私有)字段(增加其內存需求由持有Int
4個字節:
class C2(i: Int) {
val iSquared = i * i
val iCubed = iSquared * i
val iEven = i - i % 2
def mod(d: Int) = i % d
}
經過一些實驗,我確定只是在參數b
前面省略var
或val
將使它成為本地參數而不是數據成員:
class A(var a: Int)
class B(b: Int) extends A(b)
Java擴展:
$ javap -private B
Compiled from "construct.scala"
public class B extends A implements scala.ScalaObject{
public B(int);
}
$ javap -private A
Compiled from "construct.scala"
public class A extends java.lang.Object implements scala.ScalaObject{
private int a;
public A(int);
public void a_$eq(int);
public int a();
public int $tag() throws java.rmi.RemoteException;
}
請注意,由於其主要構造函數中的var a: Int
,類A
具有私有數據成員a
。 但是, B
類沒有數據成員,但其主構造函數仍然只有一個整數參數。
您可以在單個類成員的初始化過程中創建臨時變量,如下所示:
class A(b:Int){
val m = {
val tmp = b*b
tmp+tmp
}
}
德里克,
如果你有這個:
class A(a: Int) {
val aa = a // reference to constructor argument in constructor code (no problem)
def m: Float = a.toFloat // reference to constructor argument in method body (causes a to be held in a field)
}
你會發現(使用javap,例如)類中存在名為“a”的字段。 如果您注釋掉“def m”,那么您將看到該字段未創建。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.