2010-09-20 31 views
6

Neden aynı ada sahip iki tip parametrenin ("A" olarak adlandırılır) (A) adının aşağıdaki örnekte belirtilmesine izin verildiğini merak ediyorum. Bunun, tip parametrelerinin bir POOR adlandırma olduğunu biliyorum, bunu yapma.aynı ada sahip iki tür parametre

(Benim tahminim örneğin sınıf seviyesi ve işlev düzeyi, farklı bir kapsam düzeyinde bir üzerinde olmasıdır ve derleyici Cendereleme çeşit kullanıyor) 2.8.0 den

class MyTest[A](){ 
    type MyType = A 

    def checkString[A](value:A, x:MyType):A = { 
     value match { 
     case x:String => println("Value is a String") 
     case _ => println("Value is not a String") 
     } 

     x match { 
      case x:String => println("x is a String") 
      case _ => println("x is not a String") 
     } 

     value 
    } 
} 

Örnek çıktı

scala> val test = new MyTest[Int] 
test: MyTest[Int] = [email protected] 

scala> test.checkString("String",1) 
Value is a String 
x is not a String 
res7: java.lang.String = String 

scala> test.checkString(1,1) 
Value is not a String 
x is not a String 
res8: Int = 1 
+1

Bu soru, biçimlendirmeniz nedeniyle okunması daha zor hale getirilmiştir; def bloğunun kapanış ayracı ve altındaki kod gerçekten girintili olmalıdır. – Submonoid

cevap

8

Scala'da iç içe geçmiş kapsamlar, birbirlerinin sembol tablolarını gölgelemeye ücretsizdir. Bunu yapabileceğiniz tek şey türler değildir. Örneğin:

class X[A](a: A) { 
    def X[A](a: A) { 
    if (a==this.a) { 
     val X = Some(this.a) 
     X match { 
     case Some(a) => "Confused much yet?" 
     case _ => "Just because you can do this doesn't mean you should." 
     } 
    } 
    } 
} 

prensibi bir kapsam onun ad üzerinde kontrole sahip olmasıdır. Bu aptalca kullanmak (örn İki kişilik X ve üç farklı şeyler her biri için a ve A kullandıysanız, tehlikeleri var - aslında, Some yılında biri hariç X ile her kimlik değiştirir hangi küçük harf olmak zorundadır). Fakat aynı zamanda işlevsel kod yazarken de faydaları vardır - bazı değişkenleri veya türlerini yeniden adlandırmak zorunda olmanızdan endişe etmenize gerek yok.

def example = { 
    val a = Array(1,2,3,4,5) 
    val sumsq = a.map(i => i*i).sum 
    a.map(i => { 
    val a = Array.range(1,i) 
    val sumsq = a.map(i => i*i).sum // Cut and paste from above, and works! 
    sumsq + i 
    }).sum 
} 

Yani kendinizi şaşırtmak ve akıllıca olmayan karışıklığa o gücü kullanmayı tercih gücüne sahip olduğunu unutmayın.

+1

teşekkürler, bu yüzden referans ScalaReference bölüm 2? – oluies

+0

@Brent - Bunu nerede okudum veya başka bir şekilde öğrendiğimi hatırlamıyorum; Bunu dil özelliğinden çıkarabileceğimi umuyorum, ancak daha çok sohbet biçiminde karşılaştığımı gayet iyi biliyorum. –

0

Sadece ilgili değil scala. Çoğu dilde bunu yapabilirsiniz. Çünkü dediğiniz gibi değişkenler farklı kapsamda. C#

class test 
{ 
     int i; 
     void method(int i) 
     { 
      this.i = i; 
     } 
} 

yılında

bu öz tipini temsil eder. Scala'da bu işlevsellik hakkında emin değilim. Ama sorunuzun nedeni kapsam seviyesi. tipi T jenerik yöntem getInstance beyan beri

class Foo<T>{ 
    T instance; 

    void <T> T getInstance(){ 
     return instance 
    } 
} 

bir derleme hatası üretecektir değildir:

+3

Tür parametrelerini soruyor. Spesifik olmak [A]. –

1

esasında ben biz Java küçük kullanılabilir kapsam aradığınız Java gibi aynı kural kullanabilirsiniz scala de inanıyoruz Foo sınıfı parametre tipi ile aynıdır. İnanıyorum Scala durumunda o zaman davranış sağlanan tipine göre değişecektir işlev

def checkString[A] 

Sen anlatan derleyici yazmak ama dış sınıfın parametre sınıfında hiçbir bağlantısı yoktur. Ne yazık ki doğru yer bulamıyorum şu anda Scala özellikleridir.

4

Scala'nın uzmanı değilim, ancak kodunuz tam olarak beklediğim gibi davranıyor. İlk olarak, yöntemin type parametresinin sınıfa bağlı olması gerekmediğini bilmeniz gerekir. Üste | Örneğin, aşağıdaki geçerli Scala'dır.

class Test1 { 
    def test[A] (x: A) = println(x) 
} 

Ve aşağıdaki tek bu kez farklı hiç bir A tipi kullanmaz yani, aynı zamanda geçerli bir Scala kodudur.

class Test2[A] { 
    def test (x: Int) = println(x) 
} 

yüzden ilk siz gayet MyTest bir örneğini [Uluslararası] yarattı, artık açık olduğunu düşünüyorum.

scala> val test = new MyTest[Int] 
test: MyTest[Int] = [email protected] 

O zaman genel bir fonksiyonu olduğu için, derleyici A. ne tür çıkarım gerekir tür parametre A sağlamak olmadan checkString [A, Int] denilen

scala> test.checkString("String",1) 
Value is a String 
x is not a String 
res7: java.lang.String = String 

Not:

Bu zaman noktasında, Scala, x'in bir Int olması gerektiğini ve türünün sabit olduğunu bildiğinden, bunu MyTest [Int] tarafından sağladığından beri. Yani aşağıdaki kod derleme hatası verecektir.

scala> val t = new MyTest[Int] 
t: MyTest[Int] = [email protected] 

scala> t.checkString ("A", "B") 
<console>:8: error: type mismatch; 
found : java.lang.String("B") 
required: t.MyType 
     t.checkString ("A", "B") 

Şimdi derleyici, sağlanan argümanlar bakar ve onun Yani şimdi derleyici A checkString içinde [A tipi bilir

checkString (value: A, x: Int) 

tekabül edilir

checkString ("String", 1) 

olduğu bulundu Int] bir dize olmalı ve tüm bunları el ile yapıyorsanız, kodunuz böyle görünecektir.

scala> val test = new MyTest[Int] 
test: MyTest[Int] = [email protected] 

scala> test.checkString[String]("String", 1) 
Value is a String 
x is not a String 
res1: String = String 

scala> test.checkString[Int] (3, 4) 
Value is not a String 
x is not a String 
res4: Int = 3 

scala> test.checkString[Int] ("String", 4) 
<console>:8: error: type mismatch; 
found : java.lang.String("String") 
required: Int 
     test.checkString[Int] ("String", 4) 
         ^ 
+0

teşekkürler, anladığım kadarıyla, her ikisi de sınıf ve yöntem için her iki tür takma adının A birbirini izleyebildikleri halde, A: – oluies

+0

Ya ile bir bağlantıya sahip olmalarına izin vermem, çünkü CheckString [A] gölgeli MyTest'in A [A]. Bir iç blokta aynı değişken ismi gibi. –

İlgili konular