2013-04-30 152 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