2013-04-30 150 views
6

我是Scala的新手。我翻閱了幾本書,並閱讀了一些在線教程。我的第一個項目遇到了問題,所以我已經將代碼簡化爲可能出錯的最簡單的東西。scala中的構造函數,帶可變參數

我搜索谷歌和堆棧溢出爲斯卡拉/構造函數/可變參數,並閱讀了一些斯卡拉之旅。

的(幾乎)最簡單的代碼是:

class Foo(val params: Int*) 
case class Foo1(val p: Int) extends Foo(p) 
case class Foo2(val p1: Int, val p2: Int) extends Foo(p1, p2) 

object Demo extends App { 
    override def main(args: Array[String]) { 
    val f = Foo2(1, 2) 
    f.p1 
    } 
} 

的異常發生存取時p1和是

異常在線程 「主要」 java.lang.ClassCastException:scala.collection.mutable.WrappedArray $ ofInt不能轉換爲java.lang.Integer中

使用eclipse訴諸調試,我發現一個有趣的特性:當變量尋找

f Foo2 (id=23) 
    p2 2 
    params WrappedArray$ofInt (id=33) 
     array (id=81)  
      [0] 1 
      [1] 2 

那麼p1發生了什麼?

我讓您費心了一個新手的問​​題,對不起

回答

6

你沒有錯,但是編譯器。它會嘗試獲取p1p(在你的情況下,它會嘗試讓Foo2.p1Foo.params):

def p1(): Int = scala.Int.unbox(Main$$anon$1$B.super.p()); 

這顯然是一個錯誤,因爲它不能正常工作。相反,它應該在子類的ctor中分配p1

我報告了一個bug:SI-7436

+0

Woot。我的第一個Scala bug。好,謝謝。我有一個解決辦法,但我很感激幫助。這讓我想起了Fortran等價塊或Pascal變體記錄。 – 2013-04-30 12:18:16

+0

順便說一下,'class X(val p:Int *)'沒有多大意義。如果你想在構造X之後訪問'p',只需使用一個序列來代替可變參數:'class X(val p:Seq [Int])'或者class X(p:Int *){def params: Seq [Int] = p}'。 – sschaef 2013-04-30 12:22:47

1

我不能向你解釋/爲何/斯卡拉迷糊,但以下工作:

class Foo(p: Int, ps: Int*) 
case class Foo1(p1: Int) extends Foo(p1) 
case class Foo2(p1: Int, p2: Int) extends Foo(p1, p2) 

object Main extends App { 
    println(Foo1(1)) 
    println(Foo2(2, 3)) 
} 

還要注意的是,延長App時,你不想覆蓋main

+0

我很欣賞App上的評論。我是一個新手,所以我剛剛在Eclipse中使用了Hello World示例。感謝工作代碼。我有一些使用列表的東西也起作用:我的問題是理解之一。不幸的是,我很擔心代碼的「可讀性」,而變量params的意圖是保存所有參數。我想知道這是不是一個scala bug – 2013-04-30 08:21:53

+0

閱讀你的評論我想我應該提到上面的代碼也改變了你的例子的語義,因爲'Foo'的構造函數現在需要至少一個參數。可能沒有biggy,但這取決於問題域:) – fotNelton 2013-04-30 09:45:34

0

你應該在this comment一目瞭然,並回答它上面,我想應該回答你的問題;-)

+0

感謝您的迴應。我在發佈問題之前看到了這一點,但我不認爲這是正確的答案。在那個問題中,這個人想要傳遞一個Any *參數給構造函數。我不想這樣做。在Foo2的情況下,我將(p1,p2)傳遞給Any *,並且出於某種奇怪的原因,它將失去對變量p1的訪問權限,並用調用獲取參數來替換它,然後進行類轉換。請注意,在這個問題中,這個人無法獲得編譯的代碼。我編譯並運行 – 2013-04-30 08:45:32