Nasıl Scala koleksiyonları göster işlemi doğru koleksiyon türü dönebilirler?
Not: Bu sorular, sorulan, net bir cevap verebilirim kendim olarak bu sorunu gibi görünüyor gelmek oldukça sık ve giymek istiyorum bir konumu olabilir (umarım) kolay bir şekilde, üzerinden bir arama yapın
answer here benim . bir yorumda belirtildiği
Örneğin:
"abcde" map {_.toUpperCase} //returns a String
"abcde" map {_.toInt} // returns an IndexedSeq[Int]
BitSet(1,2,3,4) map {2*} // returns a BitSet
BitSet(1,2,3,4) map {_.toString} // returns a Set[String]
Bu scaladoc bakarak, bunların hepsi map
operasyon TraversableLike
, miras nasıl kullandığını her zaman en özel geçerli koleksiyon dönmek mümkün oluyor? Hatta örtülü bir dönüştürme) map
sağlayan String
,.
CEVAP
Scala koleksiyonları zeki şeyler
Koleksiyon kütüphanenin iç Scala topraklarda daha gelişmiş konularından biridir. Yüksek kinded türleri, çıkarım, varyans, implicits ve CanBuildFrom
mekanizma - inanılmaz derecede genel, kullanımı kolay ve kullanıcı bakan açısından güçlü yapmak için tüm içerir. Bakış açısı; bir API tasarımcı bu anlayış bir acemi tarafından alınacak açık yürekli bir görev değildir.
Öte yandan, gerçekten bu derinlikte koleksiyonları ile çalışmak gerekir, bu çok nadir görülür.
Haydi başlayalım o zaman...
Serbest bırakılması ile Scala 2.8, koleksiyon kütüphane tamamen yeniden yazılmış kaldırmak çoğaltılması, pek çok yöntem etkilediği için sadece tek bir yerde, böylece sürekli bakım ve ayrıca yeni toplama yöntemleri çok daha kolay olurdu, ama aynı zamanda yapar hiyerarşiyi anlamak zor.
Örneğin List
, (sırayla) bu devralır
LinearSeqOptimised
GenericTraversableTemplate
LinearSeq
Seq
SeqLike
Iterable
IterableLike
Traversable
TraversableLike
TraversableOnce
Bir avuç oldukça! Neden hiyerarşi derin bu? Görmezden XxxLike
özellikleri kısaca, her katman grubu ekler biraz işlevselliği, ya da daha optimize edilmiş versiyonu miras işlevselliği (örneğin, çekici bir öğe tarafından indeks Traversable
gerektirir bir arada drop
head
operasyon, fena halde verimsiz bir dizin oluşturulmuş sıralı). Mümkünse, tüm işlevselliği mümkün olduğu hiyerarşi kadar yukarı itilir, kullanabilirsiniz sınıflarının sayısının artırılması ve çoğaltılması kaldırılıyor.
map
sadece bir örnek. Bu yöntem uygulanır TraversableLike
(Ama XxxLike
özellikleri sadece gerçekten var kütüphane tasarımcılar, bu yüzden genellikle kabul edilir bir yöntem Traversable
en niyet ve amaçlar - geleceğim için bu kısmı kısa bir süre), ve yaygın olarak miras kaldı. Olası bazı alt sınıfta optimize edilmiş bir sürümünü tanımlamak için, ama hala aynı imza uyması gerekir. map
aşağıdaki kullanımları da söz konusu sözü gibi) göz önünde bulundurun:
"abcde" map {_.toUpperCase} //returns a String
"abcde" map {_.toInt} // returns an IndexedSeq[Int]
BitSet(1,2,3,4) map {2*} // returns a BitSet
BitSet(1,2,3,4) map {_.toString} // returns a Set[String]
Her durumda, çıktı, mümkün olan her yerde giriş olarak aynı türden. Mümkün değil, giriş türü superclasses bir bulununcaya kadar kontrol ediliryokgeçerli bir dönüş türü sunuyoruz. Bu doğru almak bir sürü iş, özellikle String
bile bir koleksiyon olmadığını düşündüğünüz zaman, sadece tek bir örtük olarak dönüştürülebilir şey aldı.
Nasıl yapılır?
Bulmacanın bir yarım XxxLike
özellikleri (benyaptıderdim olsun onlara...), kimin ana fonksiyon için Repr
yazın param (kısaca "Temsil") böylece bil, gerçek alt sınıf aslında ameliyat olmak. Örneğin TraversableLike
Traversable
, de Repr
yazın param soyutlanmış sona erdi. Bu param kullanılan ikinci yarısı bulmaca; CanBuildFrom
türü sınıf yakalayan kaynak toplama türü, hedef öğe türü ve hedef koleksiyon türü için kullanılan toplama dönüşüm işlemleri.
Daha kolay bir örnek ile bunu açıklamak!
BitSet böyle CanBuildFrom
örtülü bir örneğini tanımlar:
implicit def canBuildFrom: CanBuildFrom[BitSet, Int, BitSet] = bitsetCanBuildFrom
BitSet(1,2,3,4) map {2*}
, derlemek, derleyici CanBuildFrom[BitSet, Int, T]
kesin bir arama çalışacaktır
Bu akıllı bir parçasıdır... ilk iki tür parametreleri ile eşleşen tek bir kapsamda örtülü Var. İlk parametre XxxLike
özelliği tarafından esir olarak Repr
, ikincisi de geçerli toplama özelliği (örneğin Traversable
) tarafından esir olarak element türüdür. map
ameliyattan sonra da örtülü olarak bulunan bir tür, bu tür T
üçüncü tip CanBuildFrom
örnek parametre dayalı olarak algılanır ile parametrik. Bu durumda BitSet
.
Yani CanBuildFrom
ilk iki tür parametreleri girişi, örtülü arama için kullanılacak ve üçüncü parametre, kesmesi için kullanılan bir çıkış.
BitSet
bu nedenle iki tür maçlar BitSet
Int
, arama başarısız olur ve olayla dönüş tipi CanBuildFrom
de BitSet
olacak.
BitSet(1,2,3,4) map {_.toString}
, derlemek, derleyici CanBuildFrom[BitSet, String, T]
kesin bir arama çalışacaktır. Bu derleyici gelecek Bu örtülü içerir- Set
- onun üst deneyecek kadar BitSet içinde örtülü için başarısız olacak
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
Hangi Coll bir tip olduğu için maçları BitSet
Set
türetir BitSet
olmak başlatıldığını bunun diğer adı. A
maç olacak bir şey gibi canBuildFrom
parametrik ile tür A
, bu durumda bu algılanır String
... Böylece verimli bir dönüş türü Set[String]
.
Çok doğru uygulayan bir koleksiyon türü, sadece sağlamak için ihtiyaç bir doğru örtülü türü CanBuildFrom
ama aynı zamanda ihtiyacınız sağlamak için beton türü olan bu koleksiyon olarak sağlanan Repr
param için doğru ebeveyn özellikleri (örneğin, bu MapLike
davanın sınıflara Map
).
String
map
sağladığı için biraz daha karmaşık bir örtük dönüştürme. Örtülü dönüşüm Repr
yazın param olmak sonuçtaTraversableLike[Char,String]
- String
türetilen StringLike[String]
, alt sınıflar StringOps
.
Derleyici Char
s String
öğeleri eşleme, sonra da dönüş türü de bir dize olması gerektiğini bilir, bu nedenle de kapsam CanBuildFrom[String,Char,String]
bir şey var. Bu noktadan itibaren, aynı düzenek kullanılır.
Nasıl Scala türü silme kurtulmak mı? Y...
Nasıl Scala koleksiyonları zenginleşti...
Nasıl scala göster yineleme yapmak içi...
Nasıl Kişisel olarak scala bir ifade t...
Nasıl Scala birden çok türü sınırları ...