2011-08-02 13 views
6

Weź ten kod:Scala niejawny zakres konwersji wystawia

class Register(var value:Int = 0) { 
     def getZeroFlag() : Boolean = (value & 0x80) != 0 
    } 

    object Register { 
     implicit def reg2int(r:Register):Int = r.value 
     implicit def bool2int(b:Boolean):Int = if (b) 1 else 0 
    } 

chcę użyć go tak:

val x = register.getZeroFlag + 10 

ale jestem witany z:

type mismatch; found : Boolean required: Int 

Co się dzieje? Czy muszę zdefiniować niejawne podejmowanie funkcji, która zwraca bool?

Odpowiedz

14

Oto przykład pokazujący, jak wykorzystać swoje implicits:

object Test { 
    val register = new Register(42) 
    val x = 1 + register // implicitly calling reg2int from companion object 
    val y = register - 1 // same 
    // val z = register + 1 // doesn't work because "+" means string concatenation 

    // need to bring bool2int implicit into scope before it can be used 
    import Register._ 
    val w = register.getZeroFlag() + 2 // this works now 
    val z2 = register + 1 // works because in-scope implicits have higher priority 
} 

Dwa potencjalnie nieoczywisty rzeczy tutaj:

  • Przy ubieganiu niejawne konwersje do lub z obiektu typu Register, kompilator będzie wyglądać w obiekcie towarzyszącym Register. Właśnie dlatego nie musieliśmy jawnie wprowadzać reg2int do zakresu definiowania x i y. Jednak konwersja bool2int musi być w zasięgu, ponieważ nie jest zdefiniowana w obiekcie towarzyszącym Boolean lub Int.
  • Metoda + jest już zdefiniowana dla wszystkich obiektów w celu oznaczenia łączenia ciągów za pomocą niejawnego any2stringadd w scala.Predef. Definicja val z jest niedozwolona, ​​ponieważ domniemana konkatenacja łańcuchów ma pierwszeństwo przed reg2int (implicite znalezione w obiektach towarzyszących mają stosunkowo niski priorytet). Jednak definicja val z2 działa, ponieważ wprowadziliśmy zakres do zakresu reg2int, nadając mu wyższy priorytet.

Aby uzyskać więcej informacji o tym, jak wyszukuje kompilator implicits patrz Daniel Sobral bardzo ładne wyjaśnienie: Where does Scala look for implicits?

+0

fantastyczne. To naprawdę dobrze wyjaśnia zakres. –

+0

Właśnie zorientowałem się, że ._ na obiekcie jest konieczne do importowania rzeczy zdefiniowanych w obiekcie. Myślałem, że to będzie "implicit" (kalambur przeznaczony) – drame