2013-04-30 14 views
6

Jestem nowicjuszem Scala. Przebiłem kilka książek i przeczytałem kilka samouczków online. Mój pierwszy projekt ma problemy, więc ograniczyłem kod do najprostszej rzeczy, która może pójść nie tak.Konstruktorzy w scala z varargs

Przeszukałem Google'a i przepełnienie stosu dla scala/constructors/varargs i przeczytałem kilka wycieczek po scala.

(Prawie) najprostszym kod jest:

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 
    } 
} 

Wyjątek występuje podczas dostępu p1 i

Wyjątek nici "głównym" java.lang.ClassCastException: scala.collection.mutable.WrappedArray $ ofInt nie mogą być oddane do java.lang.Integer

Odwołanie się do debugowania przy użyciu eclipse, znalazłem ciekawą właściwość: patrząc na zmienne

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

Co się stało z p1?

Przepraszam za kłopot Ci pytanie początkującego

Odpowiedz

6

Nie są złe, ale kompilator. Próbuje dostać p1 Spośród p (w Twoim przypadku byłoby postarać się Foo2.p1 z Foo.params):

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

co jest oczywiście błędem, ponieważ nie może pracować. Zamiast tego powinien przypisać p1 w ctor podklasy.

Zgłosiłem błąd: SI-7436.

+0

Woot. Mój pierwszy błąd Scala. Ok dzięki. Mam pracę, ale doceniam pomoc. Przypomniało mi to bloki równoważności Fortran lub rekordy wariantu Pascala. –

+0

Btw, "klasa X (val p: Int *)" nie ma większego sensu. Jeśli chcesz mieć dostęp do 'p' po konstrukcji X, po prostu użyj sekwencji zamiast varargs:' class X (val p: Seq [Int]) 'lub' class X (p: Int *) {def params: Seq [Int] = p} '. – sschaef

1

nie mogę wyjaśnić/dlaczego/Scala pogubi, ale następujące utwory:

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)) 
} 

Należy również pamiętać, że przy przedłużaniu App , nie chcesz zastąpić main.

+0

Doceniam komentarz do aplikacji. Jestem początkującym, więc użyłem przykładu Hello World w Eclipse. Dzięki za działający kod. Używam list, które również działają: moim problemem jest zrozumienie. Niestety bardzo niepokoi mnie "czytelność" kodu, a celem zmiennych zmiennych jest trzymanie wszystkich parametrów. Zastanawiam się, czy to jest błąd scala –

+0

Po przeczytaniu twojego komentarza Myślę, że powinienem wspomnieć, że powyższy kod również zmienia semantykę twojego przykładu, ponieważ konstruktor 'Foo' wymaga teraz co najmniej jednego argumentu. Prawdopodobnie nie ma biggy, ale to zależy od domeny problemu :) – fotNelton

0

Powinieneś mieć spojrzenie this comment i odpowiedzi tuż nad nim, myślę, że powinna ona odpowiedzieć na problem ;-)

+0

Dzięki za odpowiedź. Widziałem to zanim napisałem pytanie, ale nie sądzę, że jest to poprawna odpowiedź. W tym pytaniu osoba chciała przekazać Any * params konstruktorowi. Nie chcę tego robić. W przypadku Foo2 przechodzę (p1, p2) na Any * i z jakiegoś dziwnego powodu traci on dostęp do zmiennej p1 i zastępuje ją wywołaniem, aby uzyskać params, a następnie rzuca klasę. Zauważ, że w pytaniu osoba nie mogła uzyskać kodu do kompilacji. Mój kompiluje i prowadzi –