2010-04-28 6 views
8

'un Miras ve tip parametreleri Scala 2.8 koleksiyon sınıflarının kaynak kodunu inceliyorum. scala.collection.Traversable hiyerarşisi hakkında sorularım var. Aşağıdaki bildirimleri bak:Traversable

package scala.collection 
    trait Traversable[+A] 
     extends TraversableLike[A, Traversable[A]] 
     with GenericTraversableTemplate[A, Traversable] 

    trait TraversableLike[+A, +Repr] 
     extends HasNewBuilder[A, Repr] 
     with TraversableOnce[A] 

package scala.collection.generic 
    trait HasNewBuilder[+A, +Repr] 

    trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] 
     extends HasNewBuilder[A, CC[A] @uncheckedVariance] 

Soru: Neden Traversable tür parametreleri [A, Traversable] ile GenericTraversableTemplate uzanmaz - neden olmasın [A, Traversable[A]]?

error: Traversable[A] takes no type parameters, expected: one 

ben GenericTraversableTemplate içinde @uncheckedVariance açıklama kullanımı da ilgisi var olduğunu tahmin: Ben Traversable[A] olarak değiştirmek çalıştığında bazı aynı yapıya sahip küçük bir program ile deneme çalıştı ve garip bir hata mesajı var bu? (Bu, işleri çalışmaya zorlamak için bir tür potansiyel olarak güvenli olmayan bir saldırı gibi görünüyor ...).

düzenlemek - (GenericTraversableTemplate farklı varyansa sahip değişken ve değişmez hem koleksiyonları için kullanıldığından öyle) this question ek açıklamanın ilgili bazı yararlı cevaplar buldum.

Soru: hiyerarşi baktığınızda, görüyorsunuz iki kez Traversable devralır HasNewBuilder (bir kez TraversableLike yoluyla ve bir kez GenericTraversableTemplate yoluyla), ama biraz farklı tip parametrelerle söyledi. Tam olarak nasıl çalışır? Neden farklı tip parametreler bir hataya neden olmaz?

cevap

16

GenericTraversableTemplate özelliğinde neden CC parametresidir. * türünde ("tip" olarak telaffuz edilir) bir normal tip parametresinden farklı olarak, bu parametre * => * türüne sahiptir ("türden yazılır"). Bunun ne anlama geldiğini anlamak için, ilk önce türler hakkında biraz arka plana sahip olmanız gerekir. İşte

val a: Int = 42 

biz 42 bkz değeri geçerli:

aşağıdaki pasajı ele alalım. Değerler içsel tiplere sahiptir. Bu durumda, değeriniz 42 ve türü Int'dur. Bir tür, birçok değeri kapsayan bir kategori gibi bir şeydir. a değişken için mümkün olan değerler hakkında bir şeyler söylüyor. Örneğin, a'un "foobar" değerini içeremeyeceğini biliyoruz, çünkü bu değer String tipindedir. Bu nedenle, değerler, soyutlamanın birinci seviyesi gibi iken, türler, değerler üzerinde bir düzeydir.

İşte soru şu: Bu adımı atmamız bizi neyin durdurdu? Değerlerin türleri olabilirse, neden türleri üstlerinde "bir şeyler" bulunamaz? Bu "bir şey" tür tür denir. Türler, hangi türlerin değerler olduğunu, türlerini sınırlayan genel kategorileri türlerinin türlerini tanımlayabilmeleridir. Bazı somut örneklere

inceleyelim:

type String 
type Int 
type List[Int] 

Bu tipler vardır ve bunlar her türlü * var. Bu en yaygın türdür (bu yüzden buna "tip" diyoruz). Uygulamada, çoğu tür bu tür var.

type List  // note: compile error 

Burada tip yapıcısı List var ama "unuttum" bu sefer onun türü parametresi belirtmek için: Ancak, bazı yoktur. Sonuçta, bu aslında bir tür, ama farklı bir tür. Spesifik olarak, * => *. Gösterimin anlamı kastedildiği için, bu tür bir parametre olarak * türünde başka türde bir tür alır ve sonuç olarak * türünde yeni bir tür oluşturur. Biz (tür * => * vardır) List tip kurucusuna (tür * vardır) Int türü geçti nerede (tür * vardır) tip List[Int] üreten, ilk örnekte görebilirsiniz.

GenericTraversableTemplate geri dönersek, ilanının tekrar bakalım: CC tür parametresi kendi başına bir parametre alır, ama bu parametre bildiriminde başka türde parametresi tarafından tanımlı değil nasıl

trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] 

Bildirim? Bu, Scala'nın CC'un * => * türünde olması gerektiğini söyleyen oldukça beceriksiz bir yoldur (önceki örneğimizde a türünün Int türünde olması gerekir). "Normal" tipi parametreler (A gibi) her zaman * türündedir. CC'u zorlamak için * => * türünde olmak zorundayız, derleyiciye bu parametre için yalnızca geçerli olan türlerin * => * türünde olması gerektiğini söyledik. Böylece:

type GenericTraversableTemplate[String, List]  // valid! 
type GenericTraversableTemplate[String, List[Int]] // invalid! 

hatırla, List taşımaktadır tür * => * (biz CC için gereken tam olarak ne), ancak List[Int] tür * vardır, bu yüzden derleyici bunu reddeder.

Kayıt için, GenericTraversableTemplate'un kendine özgü bir türü vardır: (* x (* => *)) => *. Bu, GenericTraversableTemplate'un iki türü parametre olarak alan bir tür - * türünde biri, diğer * => * - türünde olduğu ve sonuç olarak bir tür * türünü ürettiği anlamına gelir. Yukarıdaki örneğimizde, GenericTraversableTemplate[String, List], böyle bir sonuç türüdür ve hesaplandığımız gibi, * türünde (hiçbir parametre almaz).

+0

Bu kadar açık bir şekilde cevap vermek için zaman ayırdığınız için teşekkürler! Daha önce "türler" duymuştum ama şimdiye kadar ne demek istediklerini anlamadım. – Jesper