2012-04-25 14 views
8

Scala isInstanceOf ve asInstanceOf yöntemlerini sevmiyorum - bunlar uzun ve asInstanceOf istisna atabilir, bu yüzden onu çift olarak kullanmamız gerek. Daha iyi bir yol desen eşleştirmesi kullanmaktır: Scala: How do I cast a variable? ancak gerçekten basit işlemler için nispeten uzun olabilir. C# 'de' ve 'as' operatörlerimiz var, bu yüzden Scala'da bununla örtük bir tanım yapmak istedim. Böyle Benim kod görünüm:Scala kısa ve güvenli kasa operatörü

scala> class TypeCast(x:Any){ 
    | def is[T](t:Class[T]) = t.isInstance(x) 
    | def as[T](t:Class[T]):Option[T] = if(t.isInstance(x)) Option(t.cast(x)) else None 
    | } 
defined class TypeCast 

scala> implicit def TypeCastID(x:Any)=new TypeCast(x) 
TypeCastID: (x: Any)TypeCast 

scala> 123 as classOf[String] 
res14: Option[String] = None 

scala> "asd" as classOf[String] 
res15: Option[String] = Some(asd) 

It has bir avantajı - sahip ayrıca boş-nesne deseni uygulamak ancak dezavantajları:

  • classOf [T] operatörünü kullanmak gerekir - bu çok uzun

çok bu tür basit bir işlem için kapalı def bağlı

  • havai Yeniden kullanmanın pratik bir nedeni yoktur. Bunu bilmek için classOf [T] kullanılmasına gerek kalmadan bunu uygulamak için herhangi bir yolu olduğunu bilmek ister misiniz?

  • +2

    tip onay hatalarını önlemek için Manifests eklendi, bu iyidir 'isInstanceOf' ve' asInstanceOf' nispeten uzun ve sakıncalı isimleri var. Normalde dinamik tip kontrol ve dökümden kaçınmak ve bunun yerine daha iyi bir OO stili yaklaşım (polimorfizm) veya desen uyumu (fonksiyonel stil) kullanmak isteyeceksiniz. Uygunsuz isimler, bunları çok fazla kullanmamanızı tavsiye eder. Başlığınızda, "güvenli tip operatör" soruyorsunuz. Döküm, tanım gereği asla güvenli değildir. – Jesper

    +0

    Benzer yorumda bulunacağını varsaydım. Genel olarak, iyi tasarım ve desen eşleştirmesinin daha iyi olduğu konusunda size katılıyorum. Fakat bazen IMHO 'olarak' notasyonu çok daha kısa ve nettir. Örneğin, tasarımın ihtiyaç duyduğumuz kadar iyi olmadığı üçüncü parti kütüphanesini kullanabiliriz. Ayrıca Seçenek [T] yerine T'yi döndürür, böylece daha güvenlidir. Ve sonunda: bu soruya cevap en önemlisi bana Scala hakkında ek bilgi verir :) – theres

    cevap

    10

    Ayrıca, TypeCast sınıfında yaptığınız deferin içine kısaltabilirsiniz. Dolayısıyla, bir parametreyi beslemek yerine, yalnızca türüne güvenebilirsiniz. Bu onu çok kısaltır.

    scala> 123.as[String] 
    res0: Option[String] = Some(123) 
    scala> class A; class B extends A 
    defined class A 
    defined class B 
    scala> new B 
    res1: B 
    scala> res1.is[Int] 
    res2: Boolean = false 
    scala> res1.as[Int] 
    res3: Option[Int] = None 
    

    Güncelleme: gibi görünebilir

    class TypeCast(x : Any) { 
        def is[T : Manifest] = manifest.erasure.isInstance(x) 
        def as[T : Manifest] : Option[T] = if (manifest.erasure.isInstance(x)) Some(x.asInstanceOf[T]) else None 
    } 
    

    Gelecek aramalar: Örnek olarak şuna benzer olabilir ben Bence

    +0

    Benzer çözümü deniyorum ama bu talihsiz bir şekilde doğru çalışmıyor: A sınıfı; B sınıfı, A; val b = yeni B; b.as [Int], Yok yerine Bazı (örneğin-B) değerini ve ayrıca b.is [Int] değerini döndürür – theres

    +2

    Öğeleri temizlemek için bildirimleri kullanabilirsiniz. Kodu güncelleştiririm . –

    +0

    Teşekkürler! Daha önce hiç Manifest'leri duymadım. – theres

    İlgili konular