簡體   English   中英

在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前面省略varval將使它成為本地參數而不是數據成員:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM