2010-08-06 14 views
9

Dire che ho i seguenti tratti:tipo self eredità in scala

trait A 

trait B { this: A => } 

trait C extends B // { this: A => } 

errore del compilatore: illegal inheritance; self-type C does not conform to B's selftype B with A
come previsto se ho Decommentare il tipo di auto di annotazione, il compilatore è felice.

Penso che sia abbastanza ovvio perché anche C ha bisogno di questo tipo di auto. Quello che non capisco perché non può "ereditarlo" da A se il compilatore potrebbe già capire che è necessario?

Penso che potrebbe ridurre la verbosità quando si utilizzano i tipi di auto con gerarchie complicate, soprattutto se si mescolano un sacco di tratti, ognuno dei quali ha il proprio tipo di sé.

Probabilmente c'è una buona ragione per il comportamento attuale, non riesco proprio a trovare/capire di cosa si tratta.

Inizialmente ho pensato che potesse essere correlato alla linearizzazione del missaggio, ma a me sembra che non suoni qui (anche se avevo più tratti mescolati con tipi di auto più complicati).

In alcuni casi potrebbe causare ambiguità? Se è così, perché non può funzionare quando non c'è ambiguità?

O è legato ad alcune difficoltà nella corretta implementazione di esso?

Sono riuscito a trovare alcune discussioni sull'argomento (come self type is not inherited), ma per lo più limitano il problema e concludono che è come è senza troppe spiegazioni e/o soluzioni (se esiste).

risposta

1
trait C extends B with A 

non è l'unica soluzione. Si potrebbe anche avere

trait AA extends A 
trait C extends B with AA 

Vale a dire, tutto ciò che eredita l'interfaccia di A è accettata. Se devi fare affidamento su un'implementazione concreta, scegli un mixin; se l'implementazione è a carico dell'utente o se hai una buona ragione per non specificare il mixin nel tratto (ad esempio per sciogliere i problemi di dipendenza), dovresti renderlo un self-type.

+1

Penso che sia chiaro per me qual è la differenza tra mescolare in un tratto o renderlo un self-type. La mia domanda è: partendo dal presupposto che voglio i tratti precedenti con self-type e mixaggio così com'è e il compilatore può capire che ho bisogno (almeno) di A come self-type di C perché non può "aggiungerlo" automaticamente? –

+0

Penso che in molte occasioni sarebbe indesiderabile in quanto sarebbe poi compilato senza darvi la possibilità di specializzare la classe. E cosa fare quando 'A' non è disponibile nell'ambito corrente? Credo che sarebbe fonte di confusione e che l'eredità e il mixaggio dovrebbero essere resi espliciti. Inoltre, quando si desidera salvare la digitazione, è possibile definire un 'tratto CA estende C con A' e lo usa. – Debilski

+1

Debilski, stai fraintendendo la domanda. L'OP vuole che "trait C extends B" sia equivalente a "trait C estende B {this: A =>}", non a "trait C estende B a A". – Blaisorblade