2012-06-27 25 views
11
sealed class A 
class B1 extends A  
class B2 extends A 

biz sınıfta A nesnelerin bir listesi varsayarsak Listesi [A] = liste, filtre istiyoruzisInstanceOf ne zaman kullanılmalıdır ve ne zaman bir eşleşme-durum bildirimi (Scala) kullanılmalıdır? val l:

ve (yeni B1, yeni B2, yeni B1, yeni B1) B1 tipi elemanlar. Sonra bir yüklemi ihtiyacımız ve aşağıdaki iki alternatifleri kullanabilirsiniz:

l.filter(_.isInstanceOf[B1]) 

Ya

Şahsen
l.filter(_ match {case b: B1 => true; case _ => false}) 

, ben daha ilk yaklaşım gibi ama sık sık okunan, bir match-case deyimi daha kullanmalıdır sık sık (bilmediğim nedenlerden dolayı).

Bu nedenle, soru şu: match-case deyiminin yerine isInstanceOf kullanmanın sakıncaları var mı? Ne zaman bir yaklaşım kullanılmalı (ve hangi yaklaşımın burada ve neden kullanılmalıdır)?

cevap

17

Böyle filtreleyebilirsiniz: IMO, çok daha okunabilir

l.collect{ case x: B1 => x } 

olduğunu That.

+3

Ve sonunda size daha dar bir tür verir ('[B1]' Listesi). –

+0

Çok daha okunabilir görünüyor, teşekkürler.Ama bu ifadede varsayılan durum ne olacak? Bu kısayol durum bildirimi ve nasıl kullanıldığı hakkında daha fazla bilgi nerede bulabilirim? –

+0

@JohnThreepwood [bu gönderi] 'ye bir göz atın (http://ochafik.com/blog/?p=393). Bu en iyisi değil, ama yine de oldukça iyi "toplamanın nedeni". Kısaca, toplayıcı harita gibidir, ancak bu yönteme sadece * (parsiyel) * işlevi için tanımlanmış değerler için bir iş yapın. Bu durumda Scala'nın desen eşleştirmesi [PartialFunction] öğesinin üstünde yapılır (http://stackoverflow.com/questions/5668053/scala-partial-functions). Ayrıca, küme parantezleri kullanmanız gerekir. –

7

hiçbir fark bulunmamaktadır

kedi t.scala:

class A { 
    def x(o: AnyRef) = o.isInstanceOf[A] 
    def y(o: AnyRef) = o match { 
    case s: A => true 
    case _ => false 
    } 
} 

$ scalać -print t.scala

[[syntax trees at end of cleanup]]// Scala source: t.scala 
package <empty> { 
    class A extends java.lang.Object with ScalaObject { 
    def x(o: java.lang.Object): Boolean = o.$isInstanceOf[A](); 
    def y(o: java.lang.Object): Boolean = { 
     <synthetic> val temp1: java.lang.Object = o; 
     temp1.$isInstanceOf[A]() 
    }; 
    def this(): A = { 
     A.super.this(); 
    () 
    } 
    } 
} 
+0

Harika, scala derleyicisinin yapacağı arka plan bilgisi için teşekkürler. –

9

match-case avantajı da yoktur ki Daha dar tipine bağlı olarak üzerinde işlem yapmak istediğinizde nesneyi dökmeniz gerekir. bunu yaparsanız aşağıdaki Ancak

if (obj.isInstanceOf[A]) println(obj) 

: o zaman ben

if (obj.isInstanceOf[A]) { 
    val a = obj.asInstanceOf[A] 
    println(a.someField) // someField is declared by A 
} 

Böyle bir işlem yapmaksızın beri isInstanceOf kullanarak şu snippet'inde

, güzel gibi gözüküyor match-case kullanarak lehine olurdu:

obj match { 
    case a: A => println(a.someField) 
    case _ => 
} 

biraz rahatsız olduğunu Eğer "aksi" -Örnek dahil etmek zorunda ing ama (om-nom-nom tarafından ima gibi) koleksiyonları ile çalışmak, en azından eğer yardımcı olabilecek collect kullanarak Sek devralan:

collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField)) 
+0

Güzel örnekleriniz için çok teşekkür ederim. –

9

hiçbir Orada asInstanceOf'u kullanmadığınız sürece isInstanceOf kullanarak sorun.

Her ikisini de kullanan kod kırılgandır, çünkü denetim ve döküm işlemi ayrı eylemlerdir, oysa eşleştirme kullanılarak her ikisini de tek bir eyleminiz vardır.

+0

İpucu için teşekkürler, bunun için dikkat edeceğim. –

İlgili konular