Jak rzutować zmienną w Scali?

199

Biorąc pod uwagę zmienną z typem Graphics, jak ją rzutować Graphics2Dw Scali?

Eugene Yokota
źródło

Odpowiedzi:

282

Preferowaną techniką jest stosowanie dopasowania wzorca. Pozwala to z wdziękiem obsłużyć przypadek, w którym dana wartość nie jest danego typu:

g match {
  case g2: Graphics2D => g2
  case _ => throw new ClassCastException
}

Ten blok replikuje semantykę asInstanceOf[Graphics2D]metody, ale z większą elastycznością. Na przykład, możesz podać różne gałęzie dla różnych typów, skutecznie wykonując wiele rzutów warunkowych jednocześnie. Wreszcie, tak naprawdę nie musisz rzucać wyjątku w obszarze catch-all, możesz również powrócić null(lub najlepiej None) lub wejść do gałęzi rezerwowej, która działa bezGraphics2D .

Krótko mówiąc, jest to naprawdę dobra droga. Jest nieco bardziej składniowo nieporęczny niż asInstanceOf, ale dodatkowa elastyczność prawie zawsze jest tego warta.

Daniel Spiewak
źródło
19
+1, ponieważ jest to interesujące, ale trochę za dużo jak na ten scenariusz. prawda?
Eugene Yokota,
co jeśli już dopasowałem wzór, ale straciłem odniesienie do rzutowanej wartości: <kod> dopasowanie bazowe {case MyConcrete (wartość) => base.asInstanceOf [MyConcrete] .something (wartość)} </code>, czy istnieje sposób na uzyskanie „ base ”rzutowane na MyConcrete, nawet jeśli chcesz wyodrębnić„ wartość ”wykorzystując wywołanie„ nie stosuj ”wykonywane przez„ case MyConcrete (wartość) ”?
ithkuil
4
Spróbuj tego: base match { case base @ MyConcrete(value) => base.something(value) } Oczywiście, cieniowanie basejest opcjonalne. Równie łatwo można użyć innej nazwy zmiennej.
Daniel Spiewak
Nie rozumiem, w jaki sposób uzyskasz wynik dopasowania dopasowania wzorca do zmiennej? jak w Javie, jeśli był to ciąg a = (ciąg) b; jaki byłby odpowiednik Scala?
James McMahon,
@JamesMcMahonval gResult = g match { case g2: Graphics2D => g2 case _ => throw new ClassCastException }
Kevin Meredith
224
g.asInstanceOf[Graphics2D];
Eugene Yokota
źródło
36
Kiedy przyzwyczaiłem się do Scali, nauczyłem się jej nie używać asInstanceOf, ponieważ jest to sprzeczne z celem posiadania systemu typu statycznego i czuję się szczęśliwy.
Eugene Yokota,
26
Niestety, jest to częsta operacja podczas używania Swinga. W przypadku niestandardowych operacji malowania należy zastąpić metodę „public void paintComponent (Graphics g)”. Parametr Graphics jest tak naprawdę instancją Graphics2D, ale rzutowanie jest potrzebne. Wersja dopasowywania wzorców jest prawdopodobnie bardziej szczegółowa niż uzasadniona. Pamiętaj: Uwodzicielsko unikaj zaciemniającej hiperwerkotyczności i ciągłości!
hohonuuli
7
@hohonuuli Myślę, że obsada jest w porządku w tym konkretnym przypadku, ale jeśli używasz scala-swingkomponentów, parametr paintComponent jest już Graphics2D więc nie wymaga obsada
Luigi Plinge
2
Dlaczego tak długo? Dlaczego „asInstanceOf, kiedy może być tylko słowem kluczowym lub metodą„ as ”lub„ asof ”? Lub dlaczego nie przyjęli po prostu C ++ i Java jako opcji, ponieważ jest to konwencjonalne i nie ma z tym dużego problemu?
LEMUEL ADANE
16
@LemuelAdane Fakt, że w ogóle używasz rzutów, to zapach kodu, nie ma sensu ich ułatwiać.
Daenyth,