2012-06-28 15 views
6
scala> class A 
defined class A 

scala> trait B 
defined trait B 

bize veriyor:Bir özellik karıştığında neden anonim bir sınıf oluşturulur? sınıfın <code>A</code> bir nesne oluşturma

scala> new A 
res4: A = [email protected] 

Ama karışık özelliğin B ile sınıfının A bir nesne oluşturarak bize verir: Burada

scala> new A with B 
res3: A with B = [email protected] 

isimsiz sınıf var (anon ile ima edildi. Niye ya ?

Bu, A with B türünün yeni bir tür olarak kabul edildiğinden (ve daha önce tanımlayıcıyla tanımlanmayan) bu mu?

cevap

13

Bu, yalnızca A with B'un yeni bir tür olarak görülmesi gerektiğinden değil. Scala tipi sistemde, A with B'a karşılık gelen bir sınıf varsa doğrudan sorun olmaz. o köprüyü de karışmış durumda özelliklerin tüm yöntemler için yöntemleri içermesi gerekir, çünkü Anonim sınıf oluşturulur.

oluşturulur anonim sınıf nesnesi tüm yöntemlerin uygulamaları olması gerektiğini olmasının sebebi A ve B'dan tüm yöntemler. JVM bayt kodu düzeyinde, bu, birden fazla sınıfın miras alınıp alınmayacağını ve birden fazla kalıtım modelinin JVM'de desteklenmeyeceğini belirtir. özellik T hiçbir yöntem uygulamaları varsa

  1. bir oluşturur: Bir özelliği oluşturduğunuzda

    Scala şunları yapar (ancak bunu aramak istediğiniz veya mixin kompozisyon) çoklu mirası simüle etmek Özellikdeki tüm yöntemleri tanımlayan arayüz.
  2. T özelliğinin, yöntem uygulamalarına sahip olması durumunda, numaralı belgede somut yöntemlerin her biri için statik bir yöntemi olan bir T$class sınıfı oluşturur. Bu statik yöntem, T'daki karşılık gelen yöntemle aynı gövdeye sahiptir, ancak imzası, this parametresini içerecek şekilde değiştirilmiştir.T varsa:

    def foo(x: Int) = x 
    
  3. sonra T$class

sahip olacaktır:

<static> def foo($this: T, x: Int) = x 

bir sınıf A ve bazı özellik T arasında mixin bileşimi ile elde edilen sınıfı, daha sonra özel bir köprü yöntemi ileten oluşturulan olacaktır Gövde içeren statik yönteme çağrı. Bu şekilde, yöntemin gövdesi, T'da karışan her sınıfta çoğaltılamaz. Bu nedenle, anonim sınıfın oluşturulması gerekir - T'da her yöntem için tanımlanan köprü yöntemlerine sahip olması gerekir.

İşte bir örnek. Mixin kompozisyonu yaparak yeni bir sınıf oluşturduğunuzda, ör. new A with T çağırır: derleyici aslında doğrusu callsite doğrudan statik yöntemleri çağırmak için foo için callsites yeniden verebilecek

class A { 
    def bar = println("!") 
} 

<interface> T { 
    def foo(x: Int): Int 
} 

class T$class { 
    <static> def foo($this: T, x: Int) = x 
} 

class $anon extends A <implements> T { 
    // notice that `bar` is inherited, but `foo` is not 
    <bridge> def foo(x: Int) = T$class.foo(this, x) 
} 
new $anon 

Uyarı:

class A { 
    def bar = println("!") 
} 

trait T { 
    def foo(x: Int) = x 
} 

new A with T 

derleyici kabaca böyle bir şey için yeniden yazmak olacaktır bir köprü yönteminden daha. Bu şekilde yapılmamasının nedeni, o zaman artık alt-polimorfizmi desteklemeyeceği içindir.

+1

+1 özellikle bir örnek göstermek için! –

+1

Harika cevap, çok teşekkür ederim. –

+0

'-Xprint: mixin' argümanı ile' scalac'ı çağırmanın Scala'nın yarattığı kesin yapıyı göstereceğini unutmayın. -Xshow-phase-'-Xprint:' ile kullanılabilecek diğer aşamaları gösterir. – outis

6

Evet. tür türünüz hala A with B ise, her iki arabirimi uygulayan temel Java sınıfının olması gerekir. Bununla ilgili yanlış bir şey yok, eğer yüzlerce kez bu şekilde nesneler oluşturursanız, muhtemelen yüzlerce sınıf dosyanız olacaktır. Böyle bir durumda, özel bir class AB extends A with B oluşturmak ve daha sonra new AB'u başlatmak isteyebilirsiniz.

Bir yan not olarak, doğrudan özellikleri de başlatamazsınız, ör. new B çalışmıyor. Burada da açık bir sınıf oluşturmanız gerekiyor, ör. new B {}, yine bir sentetik ('anonim') sınıfı ile sonuçlanır.

+0

Teşekkür ederiz. Adanmış bir sınıf performansa göre daha anlamlı olduğunda, anonim nesnelerin sayısı ne olurdu? 10, 100, 1000 veya daha fazla? –

+3

Sadece bu sınıfın her örneği için değil, kodunuzda bunun her oluşumu için yeni bir sınıf oluşturacaktır. Yani yüzlerce kod satırında 'B ile yeni A' olmadıkça, bu pek olası değildir, bir sorun olmamalı. – drexin

+0

@John - Bilmiyorum. Şahsen ben 10 durumda bir sınıf olurdu; Bu, B ile A'nın başlatıldığı 10 farklı noktadan oluşur (@drexin'in doğru olarak söylediği gibi). Çok sık bu tür vakalarım yok. –

İlgili konular