2011-08-12 18 views
14

Zgaduję, że ze względu na kompatybilność, typ parametrów vararg Any* jest Array [Any] - proszę poprawić to, jeśli się mylę. Jednak to nie wyjaśnia następujący błąd:Scala: Konstruktor biorąc Seq lub varargs

class Api(api_url: String, params: Seq[(String, String)]) { 
    def this(api_url: String, params: (String, String)*) 
    = this(api_url, params.seq) 
} 

Ten kod nie kompiluje, ale daje ostrzeżenie:

double definition: constructor Api:(api_url: String, params: (String, String)*)Api and constructor Api:(api_url: String, params: Seq[(String, String)])Api at line 13 have same type after erasure: (api_url: java.lang.String, params: Seq)Api

Więc jak mogę określić konstruktor biorąc albo varargs lub sekwencja?

Odpowiedz

24

Sposób podejmowania varargs jest również zawsze biorąc sekwencję, więc nie ma potrzeby zdefiniować pomocniczy konstruktor lub metodę przeciążenia.

Biorąc

class Api(api_url: String, params: (String, String)*) 

można nazwać jak ten

new Api("url", ("a", "b"), ("c", "d")) 

lub

val seq = Seq(("a", "b"), ("c", "d")) 
new Api("url", seq:_*) 

Również w swoim pytaniu, jesteś wywołanie metody nast parametru params. Prawdopodobnie nie robi to, co zamierzałeś. Sekwencja seq służy do tego, aby operacje na wynikowym zbiorze były wykonywane sekwencyjnie, a nie równolegle. Metoda została wprowadzona z równoległymi kolekcjami w wersji 2.9.0 programu Scala.

To, czego prawdopodobnie chciałeś użyć, to toSeq, które zwraca kolekcję, z której jest ona używana po konwersji na Seq (lub samo, jeśli jest już Seq). Ale ponieważ parametry varargs są już wpisane jako Seq, to ​​i tak nie ma operacji.

+0

Dziękuję, to było naprawdę pomocne. :) – wen

+3

Chciałbym zaznaczyć, że adnotacja typu ': _ *' jest tym, co naprawdę wywołuje konstruktor przy użyciu argumentu sekwencji zgodnego z konstruktorem varargs. Więcej szczegółów: http://stackoverflow.com/questions/6051302/what-does-colon-underscore-star-do-in-scala –

9

Nie: faktycznie, Any* jest właściwie prawie identyczny z Seq[Any], a nie z Array[Any].

disambiguate między nimi, można zastosować technikę, aby dodać obojętne parametr niejawny, aby podpis innego:

class Api(api_url: String, params: Seq[(String, String)]) { 
    def this(api_url: String, params: (String, String)*)(implicit d: DummyImplicit) = 
    this(api_url, params) 
} 
+0

... czy to nie ... naprawdę odrażające? – wen

+5

Cóż, możesz zaoferować mniej "obrzydliwe" rozwiązanie! –

+0

Kiedy wymyślę jedną, zrobię to. Na razie po prostu zarysuję konstruktor 'varargs'. ^^ – wen

1

Przypuszczam, że chciałbyś, aby metoda wywoływała ładniejsze i tak jawne wywoływanie z _* nie jest opcją. W takim przypadku możesz rozwiązać problem z przeciążeniem metody.

class Api(api_url: String, params: Seq[(String, String)]) { 
    def this(api_url: String, param : (String, String), params: (String, String)*) 
    = this(api_url, param +: params) 
    def this(api_url: String) 
    = this(api_url, Seq()) 
}