2012-10-06 152 views
4

我是scala的新手,需要對涉及類的構造函數的以下代碼片段進行說明。在scala中構造函數定義語法需要說明

class sample (a: Int, b: Int) { 
/* define some member functions here */ 
} 

我完全可以接受的變量ab是私有的類sample

class sample (val a: Int, val b: Int) { 
/* define some member functions here */ 
} 

在這種情況下,是ab公開訪問?在構造函數的參數列表中添加val關鍵字的確切效果是什麼?如果我使用def關鍵字而不是val,它是否也具有相同的效果?

回答

7
class sample (a: Int, b: Int) 

a和b在這種情況下是私人的。與javap的拆卸表示a和b是不是類的部分(Scala中調用這些類字段):

public class Sample extends java.lang.Object implements scala.ScalaObject{ 
    public Sample(int, int); 
} 

a和b前面有VAL。使用javap反彙編顯示a和b現在是Sample中的公共字段。

class sample (val a: Int, val b: Int)

public class Sample extends java.lang.Object implements scala.ScalaObject{ 
    public int a(); 
    public int b(); 
    public Sample(int, int); 
} 

隨着def而不是val它不會編譯構造。 def用於定義功能。不知道您是否可以在構造函數中使用def作爲參數。

此外,請注意,私人和受保護的行爲,如你所期望的。鑑於此:

class Sample(private val a: Int, protected val b: Int, val c: Int) 

拆開與javap的以下內容:

public class Sample extends java.lang.Object implements scala.ScalaObject{ 
    public int b(); 
    public int c(); 
    public Sample(int, int, int); 
} 
+0

是的我嘗試編譯'def',但它沒有工作:) – Raj

6

以下Scala的類示出了用於構造參數四種可能性(3點不同的聲明,其中一個有兩個作用):

class ConstructorParams (local:Int, prvt:Int, val readonly:Int, var writable:Int) { 
    def succ_prvt() = prvt + 1 
} 
  1. 的第一個參數,local,不被任何方法引用。它僅作爲構造函數中的局部變量存在(它可以由字段初始值引用而不改變它;嘗試將val foo = local添加到構造函數中)。
  2. 第二個,prvt,被引用的方法,所以它成爲一個私人領域。
  3. 第三個0123'聲明符創建了一個getter和一個專用的後臺字段。
  4. 第四位的var聲明者創建了一個getter和一個setter以及一個專用的後臺字段。

特別要注意,如果沒有valvar聲明符構造函數的參數是私有的(這是無障礙的事情),只有當它在類中的一個函數的引用;否則,它是本地的(這是一個範圍問題)。

從技術上講,最後三個參數以局部值和私有字段的形式存在(初始化爲本地值),但是這種區別不應該太大,所以你可以把它放在腦海中。

def作爲參數聲明沒有多大意義,因爲它用來引入一個新函數,而不是聲明一個值/變量名;它也不用於函數參數(構造函數參數與函數參數密切相關)。由於函數是第一類,因此您可以使用函數類型而不是特殊聲明器來聲明參數包含函數。

打印出編譯器使得ConstructorParams什麼通過傳遞-Xprint:constructors編譯器,我們得到(添加註釋):

class ConstructorParams extends Object { 
    /* 2nd (no-declarator) param becomes private field due to reference in `succ_prvt()` */ 
    <paramaccessor> private[this] val prvt: Int = _; 

    /* `val` becomes private field + getter */ 
    <paramaccessor> private[this] val readonly: Int = _; 
    <stable> <accessor> <paramaccessor> def readonly(): Int = ConstructorParams.this.readonly; 

    /* `var` becomes private field + getter + setter */ 
    <paramaccessor> private[this] var writable: Int = _; 
    <accessor> <paramaccessor> def writable(): Int = ConstructorParams.this.writable; 
    <accessor> <paramaccessor> def writable_=(x$1: Int): Unit = ConstructorParams.this.writable = x$1; 

    /* causes `prvt` constructor param to become private field */ 
    def succ_prvt(): Int = ConstructorParams.this.prvt.+(1); 

    def <init>(local: Int, prvt: Int, readonly: Int, writable: Int): ConstructorParams = { 
     ConstructorParams.this.prvt = prvt; 
     ConstructorParams.this.readonly = readonly; 
     ConstructorParams.this.writable = writable; 
     ConstructorParams.super.<init>(); 
     () 
    } 
} 

上面的例子類編譯爲Java等價的:

public class ConstructorParams { 
    /* 2nd (no-declarator) param becomes private field due to reference in `succ_prvt()` */ 
    private final int prvt; 

    public int succ_prvt() { 
     return this.prvt + 1; 
    } 

    /* `val` becomes private field + getter */ 
    private final int readonly; 
    public int readonly() { return this.readonly; } 

    /* `var` becomes private field + getter + setter */ 
    private int writable; 
    public int writable() { return this.writable; } 
    public void writable_$eq(int x$1) { 
     this.writable = x$1; 
    } 

    /* 1st param is local, since it's not referenced in any other methods */ 
    public ConstructorParams(int local, int prvt, int readonly, int writable) { 
     /* parent constructor is invoked implicitly, so not repeated here */ 
     this.prvt = prvt; 
     this.readonly = readonly; 
     this.writable = writable; 
    } 
} 

如果您在ConstructorParams上使用javap(與Brian一樣)和-p參數,您將看到一個類簽名等同於上述Java源代碼中的類簽名。