2012-03-04 24 views
6
  • Ho 3 classi di Scala (A, B, C).
  • Ho una conversione implicita da A -> B e uno da B -> C.

Ad un certo punto nel mio codice, voglio chiamare un metodo C su A. E 'possibile? Una correzione che ho trovato è quella di avere una conversione da A -> C, ma sembra un po 'ridondante.Conversione implicita transitivo Scala

Nota:

  • Quando chiamo metodi B sulla funziona.
  • Quando chiamo i metodi C su B funziona.
  • Quando chiamo i metodi C su una mi dice che non ha trovato il metodo nel corpo di un

Grazie ...

+6

Suggerimento: questo sembra più _transitivity_ che _associativity_. E tu non sei il primo a volerlo per gli impliciti di Scala. Anche 'A -> C' è probabilmente un errore di battitura per' B -> C' nella tua seconda riga? –

+0

Grazie. Ero di fretta. –

+3

anche dare un'occhiata a: [how-can-i-chain-implicits-in-scala] (http://stackoverflow.com/questions/5332801/how-can-i-chain-implicits-in-scala) –

risposta

6

Sembra un po 'ridondante, ma la conversione A -> C è esattamente ciò che si dovrebbe fornire. Il motivo è che se gli impliciti sono rari, le catene transitive sono anche rare e probabilmente sono ciò che si desidera. Ma se gli impliciti sono comuni, è probabile che sarete in grado di trasformare qualsiasi cosa in qualcosa (o, se aggiungete un implicito dall'aspetto pratico, improvvisamente cambieranno tutti i tipi di comportamento perché avete aperto diversi percorsi per la conversione implicita).

È possibile avere le conversioni implicite per Scala, tuttavia, se si specifica che deve essere eseguita. La chiave è usare i generici con <% che significa "può essere convertito in". Ecco un esempio:

class Foo(i: Int) { def foo = i } 
class Bar(s: String) { def bar = s } 
class Okay(b: Boolean) { def okay = b } 
implicit def to_bar_through_foo[T <% Foo](t: T) = new Bar((t: Foo).foo.toString) 
implicit def to_okay_through_bar[U <% Bar](u: U) = new Okay((u: Bar).bar.length < 4) 

scala> (new Foo(5)).okay 
res0: Boolean = true 
+0

Grazie per la rapida risposta. –

+0

Sì, ho provato la <% cosa e ha funzionato. Ma ha anche generato una strana implicita da Array [String] => Errore del compilatore di unità. Quindi sono tornato a colmare il divario manualmente. Serbatoi per il tuo aiuto. –

9

Sembra che hai fatto un errore di battitura quando hai scritto la domanda . Intendevi dire che hai conversioni implicite da A -> B e B -> C e che trovi una conversione A -> C ridondante?

Scala ha una regola che si applica solo uno conversione implicita quando necessario (ma mai due), quindi non si può solo aspettare Scala per comporre magicamente A -> B e B -> C di effettuare la conversione è necessario. Dovrai fornire la tua conversione A -> C. Non è ridondante.

+4

Uno dei motivi per cui questo è il caso è che potrebbero esserci più possibilità per il tipo medio. Se esistono conversioni implicite 'A -> B1',' B1 -> C' e 'A -> B2',' B2 -> C', il compilatore non sarebbe in grado di indovinare quale si desiderava. – hammar

+0

Grazie per la rapida risposta. –

+0

con 'implicit def transitivo [A, B, C] (implicito a2b: A => B, b2c: B => C): A => C = (a: A) => b2c (a2b (a)) 'È teoricamente possibile fare una risoluzione transitiva. Ma in questo caso ogni 'implicitamente [A => B]' diverge, in quanto vi è implicito '$ conforms [A]: A => A' - l'algoritmo di risoluzione termina il ciclo. – phadej

Problemi correlati