2012-03-07 12 views
6

Ecco una semplificazione di ciò che ho incontrato. Questo compila:Impliciti e ordine di dichiarazione

trait A { implicit val x = 1 } 
trait B extends A { val y = implicitly[Int] } 

Anche se questo non lo fanno (non riusciva a trovare valore implicito):

trait B extends A { val y = implicitly[Int] } 
trait A { implicit val x = 1 } 

ho cercato di fare le mie intenzioni chiare specificando un auto-tipo: trait A { this: B => ... }, ma senza alcun risultato .

Come faccio a gestire questo tipo di dipendenze senza preoccuparmi di come è strutturato il mio codice?

risposta

11

è necessario dichiarare il tipo in modo esplicito, almeno per questi ultimi uno

trait B extends A { val y = implicitly[Int] } 
trait A { implicit val x : Int = 1 } 

Le regole per la visibilità implicita è diverso se il suo tipo viene dichiarato esplicitamente o meno. Se non lo è, l'implicito è disponibile (come implicito) solo dopo il punto di dichiarazione.

Il motivo è che l'inferenza di tipo può diventare troppo difficile se il tipo non è stato dichiarato (come nella routine ricorsiva). In molti casi, l'inferenza sarebbe facile (come nel tuo codice) ma le specifiche devono essere chiare.

+0

E gli oggetti impliciti? Potresti indicarmi le parti delle specifiche riguardanti la risoluzione degli impliciti? 'tratto X; la caratteristica B estende A {val y = implicitamente [X]}; tratto A {oggetto implicito x estende X} ' – elbowich

+1

Ci scusiamo per la risposta tardiva. Dopo uno sguardo più che superficiale nelle specifiche, non sono riuscito a trovare la regola. Tuttavia, è menzionato in [questo bug report] (https://issues.scala-lang.org/browse/SI-801), sembra che sia ciò che fa l'implementazione, ma non ha ancora raggiunto le specifiche. Non capisco perché non dovrebbe funzionare con un oggetto implicito. –

Problemi correlati