2011-08-23 14 views
17

Bir sınıf değişkeninin değerini tanımlamak için bir "eşleşme" deyimini nasıl kullanabilirim? Aşağıdaki geçersiz olduğunu ve kabul edilebilir bir varyantı bulamıyor - eğer başka ... ... else if else ...Scala "match" deyiminde sınıfları nasıl eşleştirebilirim?

val c: Class[_] = classOf[Int] 
val what = c match { case classOf[Int] => "int!"; case classOf[Float] => "float!" } 

derleyici yakınır: error: not found: type classOf

Ve tabii bu tip bilgiler silinir çünkü ben Class[Int] kullanamazsınız:

c match { case Class[Int] => "int!"; case Class[Float] => "float!" } 
error: type Class of type Class does not take type parameters. 

Ben de denedim varyantları Int.class gibi tüm boşuna. (Ve gerçekten dizeleri dönüştürmek istemiyorum: Derleyicinin yeniden adlandırılmış sınıfları değiştirdiğinin farkındayım.)

Yoğun muyum muyum yoksa Scala kör noktaya mı geldim?

+1

Peki, aşağıda cevapları cevapları için doğru (ve teşekkür vardır!) ama giderek daha fazla görünüyor * bu Scala'da bir tür çirkin delik. Sınıflar tekildir, bu yüzden onları verimli bir şekilde eşleştirmek için değişkenlere atamak zorunda olmanız için hiçbir neden yoktur - ya da muhafızlar ya da ayrı ifadeler olarak yazılan, basamaklı bir dizi ifs kullanmaya başvurma. Ama görünüşe göre, öyle. – Tim

cevap

18

(yani. bir val) onlar için, sen türüne maç olamaz

scala> val c: Class[_] = classOf[Int] 
c: Class[_] = int 

scala> val ClassOfInt = classOf[Int] 
ClassOfInt: java.lang.Class[Int] = int 

scala> val ClassOfFloat = classOf[Float] 
ClassOfFloat: java.lang.Class[Float] = float 

scala> val what = c match { 
    |  case ClassOfInt => "int!" 
    |  case ClassOfFloat => "float!" 
    | } 
what: String = int! 

Not (yani. Sınıf [Uluslararası]) nedeniyle silme Sınıf [T], farklı tip örneğinin bulunması dolayısıyla aynı sorunu ve 'stabil tanımlayıcı' sınıfı yerleştirilmesi karşılaşılan

scala> val what = c match { 
    |  case _: Class[Int] => "int!" 
    |  case _: Class[Float] => "float!" 
    | } 
warning: there were 2 unchecked warnings; re-run with -unchecked for details 
what: java.lang.String = int! 
+1

Kararlı belirleyiciler - evet, bundan korkuyordum. İğrenç. "Tipine uymayacağınızı unutmayın (örn. Sınıf [Int])" - evet, söz konusu. Yine de teşekkürler! – Tim

+0

(Ayrıca, bu cevabın potansiyel olarak aşağıdakilerden daha verimli olduğuna da dikkat etmeliyim, bu yüzden aradığım şeye daha yakın. Tekrar teşekkürler! – Tim

+1

Önemli bir not: 'val' isminin bir büyük harfle başlaması gerekir. – vpipkt

26

ayrıntılı vaka karşılaştırma çalışır: Elbette

val what = c match { 
    case q if q == classOf[Int] => "int!" 
    case q if q == classOf[Float] => "float!" 
} 

, bir küçük harf tanımlayıcı olan classOf zaten bir vaka açıklamada doğrudan çalışmamalıdır. Eğer if -guard ile gitmek gerekir böylece Ancak, ne bu durumda kaçan bir

case `classOf`[Int] 

çalışır. Eğer istikrarlı bir tanımlayıcı oluşturmak eğer sınıf değerlerine eşleşebilir

+0

Evet, if-guard, 'case' ifadesini bir' if/else' ifadesi kümesine dönüştürür. Çirkin, ama oldukça doğru. Teşekkür ederim! – Tim

+0

Bu soruya akıllıca bir çözüm – javadba

0

aşağıdaki uyarı pratik değildir ... zamanında ayırt edilemez olduğu anlamına gelir . Bir sonraki en iyi şeyin 'else if' ifadeleri olması gerekiyordu.

bu yöntemi kullanarak:

private def is[T <: AnyRef : Manifest](implicit cls: Class[_]) = 
    cls == manifest[T].runtimeClass 

yazabilirim:

implicit val arg = cls 
    if (is[ClassA]) ... 
    else if (is[ClassB]) ... 
    ... 
    else throw new IllegalArgumentException("Unknown class: " + cls) 
+0

Ha ha. Yine kendi yanıtımı buldum ama bunun için oy kullanamam. –

0

devralma düşünün:

val what = c match { 
    case q if classOf[Int].isAssignableFrom(q) => "int!" 
    case q if classOf[Float].isAssignableFrom(q) => "float!" 
} 
İlgili konular