2013-04-30 11 views
5

Birisi aşağıdaki kodun neden bir MatchError'a neden olduğunu açıklayabilir mi? Bir MatchError bu durumda ne anlama geliyor? Bu işe yaramazsa VerilenCompanion Object Değerlerini ve Scala MatchError öğelerini geçersiz kılma

class A { 
    def g = A.f 
} 

object A { 
    val f = "Object A" 
} 


class B extends A { 
    override val A.f = "Object B" 
} 

val b = new B 
b.g 

, buna def benzer bir arkadaşı nesne val veya geçersiz kılmak için bir yol var?

cevap

3

İlk olarak, neden bir MatchError görüyorsunuz. Bir nesne üzerindeki bir değer (A.f), kararlı bir tanımlayıcı olarak kabul edilir (Scala referansı, "Kararlı üyeler [...] nesne tanımları veya uçucu olmayan türlerin değer tanımları tarafından tanıtılan üyelerdir"). desen eşleştirme içine

bir görev kullanılan
object A extends scala.AnyRef { 
    ... 
    private[this] val f: String = "Object A"; 
    <stable> <accessor> def f: String = A.this.f 
} 

, derleyici "desugars" Bu kararlı tanımlayıcı atama (kararlı olmak gerekli bir koşuldur): Burada

gibi Typer çıkışı nasıl göründüğü ve

<synthetic> private[this] val x$1: Unit = ("Object B": String("Object B") @unchecked) match { 
    case A.f =>() 
} 

"Object A" desenine karşı "Object A" ile eşleşemez, bu nedenle MatchError atar.

Büyük sorunuz için: tamamlayıcı bir nesnede bulunan değerleri ve yöntemleri geçersiz kılmanız/kullanmamalısınız. Polimorfizm, sınıflara ve örneklerine, statik yöntemlere veya değerlere uygulanmaz. Programınızı, eşlik eden bir nesnede geçersiz kılmayı/kusurları geçersiz kılmayan, düşünmeniz için muhtemelen daha iyi bir yol vardır.

+0

Teşekkür yapabilirsiniz! Genelde eşlik eden nesneleri geçersiz kılma ihtiyacında size katılıyorum, ancak burada yapmak istediğim neden, başka bir yöntemle eşlik eden nesnenin içindeki bir yöntemi değiştirmek istediğim test amaçlıdır. Ayrıca, bazı diller statik yöntemlerin geçersiz kılmasına izin verir. – deepkimo

1

Bu ilginç! Eğer bir dosyaya sınıf tanımlarını koymak ve scalac -print test.scala kullanarak derlemek Eğer bu derleyici değeri olduğunu görmek için kontrol bir maç gerçekleştiren bir başlatma sahip bir sınıf B yarattığını gösteriyor

[[syntax trees at end of     cleanup]] // scala 
package <empty> { 
    class A extends Object { 
    def g(): String = A.f(); 
    def <init>(): A = { 
     A.super.<init>(); 
    () 
    } 
    }; 
    object A extends Object { 
    private[this] val f: String = _; 
    <stable> <accessor> def f(): String = A.this.f; 
    def <init>(): A.type = { 
     A.super.<init>(); 
     A.this.f = "Object A"; 
    () 
    } 
    }; 
    class B extends A { 
    <synthetic> private[this] val x$1: runtime.BoxedUnit = _; 
    def <init>(): B = { 
     B.super.<init>(); 
     B.this.x$1 = { 
     case <synthetic> val x1: String = ("Object B": String("Object B")); 
     case5(){ 
      if (A.f().==(x1)) 
      { 
       val x2: String = x1; 
       matchEnd4(scala.runtime.BoxedUnit.UNIT) 
      } 
      else 
      case6() 
     }; 
     case6(){ 
      matchEnd4(throw new MatchError(x1)) 
     }; 
     matchEnd4(x: runtime.BoxedUnit){ 
      scala.runtime.BoxedUnit.UNIT 
     } 
     }; 
    () 
    } 
    } 
} 

böyle bir şey göreceksiniz val A.f'u geçersiz kılmak için kullandığınız değer if (A.f().==(x1)) özgün değerine eşittir. Çok kullanışlı görünmüyor değil mi? Eşit değilse, case6() numaralı telefonu arayarak eşleşme hatasını atar. class B'un tanımını override val A.f = "Object A" olarak değiştirerek bunu doğrulayabiliriz.

class B extends A { 
     override val A.f = "Object A" 
} 

scala> val b = new B 
b: B = [email protected] 

Peki, nasıl düzeltilir? Sadece açıklama,

class B extends A { 
     override def g = "Object B" 
} 
scala> val b = new B 
b: B = [email protected] 

scala> b.g 
res1: String = Object B 

veya

class B extends A { 
     val f = "Object B" 
} 
scala> val b = new B 
b: B = [email protected] 

scala> b.f 
res0: String = Object B 
+0

Özelliklerini kullanmayı düşünebilirsiniz: http://stackoverflow.com/a/7625150/1274818 – tysonjh

+0

Düzeltmeleriniz, bu basit kod örneğini almanın akıllıca bir yoludur, ancak aradığım şey tam olarak değil; Orijinal Af yöntemi. – deepkimo

+0

Evet, özellikler bunu yapılandırmanın iyi bir yoludur, ancak benim durumumda, ana kodu değiştirmeden zaten var olan kodu sınamak istiyorum. – deepkimo