Jeśli jesteś podobny do mnie, czasami chcesz pisać ulepszone metody do kolekcji lub sekwencji Scala, ale chcesz powiązać typ kolekcji, a także typ elementu, a nie tylko upcast na Seq [T].Jak można pisać ogólne metody poprawy Scala, które wiążą typ kolekcji, a także typ elementu?
6
A
Odpowiedz
7
Jest sposób, aby to zrobić, i to działa tak:
object enhance {
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class Enhance[T, S[E] <: SeqLike[E, S[E]]](seq: S[T]) {
def first3(implicit cbf: CanBuildFrom[S[T], T, S[T]]) = seq.take(3)
def foo = seq.iterator
def goo(implicit cbf: CanBuildFrom[Nothing, T, S[T]]) = foo.take(3).to[S]
def moo[U](f: T => U)(implicit cbf: CanBuildFrom[S[T], U, S[U]]) = seq.map(f)
}
}
Stosując wzór rodzaj podpisu powyżej, ulepszone metody są świadomi zarówno typu elementu T
(np Int
lub String
) i typem o wyższej ładowności typu S
(np. List
lub Vector
), dzięki czemu może on zwrócić dokładnie ten typ sekwencji, na który został wywołany.
Wiele metod sekwencji może wymagać CanBuildFrom
implicits, które są dodawane do metod jako niejawne parametry, gdzie są potrzebne w powyższych przykładach.
Poniżej bieg próbkę, wykazując pożądane wyższe kinded rodzajów powrotne kolekcji:
scala> import enhance._
import enhance._
scala> (1 to 10).toList.first3
res0: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.first3
res1: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.goo
res2: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.goo
res3: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.moo(_.toDouble)
res4: List[Double] = List(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
scala> (1 to 10).toVector.moo(_.toDouble)
res5: Vector[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
Powiązane problemy
- 1. Typ kolekcji Scala dla filtra
- 2. scala dynamicznie określana typ
- 3. Scala typ abstrakcyjny reprezentujący typ podklasy
- 4. Java otrzymuje ogólny typ kolekcji
- 5. Jak ustalić, czy typ jest typem kolekcji?
- 6. Nieoczekiwana Scala Typ mapy
- 7. XDocument.Validate - Oczekiwany typ Typ elementu błędu
- 8. scala typ krotka skład
- 9. Scala Generics Typ Ograniczenia
- 10. statyczny typ powrót Scala makropolecenia
- 11. Scala wielokrotny typ dopasowywania wzorców
- 12. Dlaczego scala używa refleksji do wywołania metody na typ strukturalny?
- 13. Scala REPL: Jak znaleźć typ funkcji?
- 14. Jak zmienić te ogólne metody?
- 15. typ Własna dziedziczenie w Scala
- 16. Sprawdzanie Typ funkcji w Scala
- 17. Zwróć typ Scala za/plon
- 18. Typowy typ metody Java argument
- 19. decltype dla metody klasy typ
- 20. Jak przekonwertować JSON na typ w Scala
- 21. Typ funkcji z parametrami Implicit w Scala
- 22. Nie można dopasować oczekiwany typ `a„z rzeczywistego typu `[a]”
- 23. Typ zwrotu kolekcji z LINQ kwerendy
- 24. Jak przekazać typ Swift jako argument metody?
- 25. Typ kolekcji F dla typów mieszanych
- 26. Jak uzyskać typ metody żądania w `app.all()`?
- 27. granice Scala niższy typ i kowariancji
- 28. Jak utworzyć typ powrotu dla metody ogólnej?
- 29. Jak wymusić typ zwrotny metody statycznej?
- 30. Typ obietnica typ rodzajowy
Również można określić klasę jako 'ukryte klasy Ulepsz [T, S [k] <: IterableLike [E, S [E]]] (seq: S [T]) {'i wtedy nie będziesz potrzebował' asInstanceOf ' –
To nie zadziała, jeśli użyjesz' map' lub jakiejkolwiek innej metody, która bierze 'CanBuildFrom' w nowej metodzie wdrożenia. Rezultat wypadłby po prostu jako "Seq". Musiałbyś przekazać odpowiedni niejawny 'CanBuildFrom' do klasy' Enhance' lub do metody. – Kolmar
Dzięki @ НиколайМитропольский i Kolmar, obie te modyfikacje są bardzo przydatne! Przebudowałem swoją oryginalną odpowiedź, aby pokazać je w akcji. – eje