2015-06-18 30 views
7

C'è un modo per definire un insieme di alternative di un tipo comune:Scala - mutuamente esclusivi tratti

trait Mutability 
trait Mutable extends Mutability 
trait Immutable extends Mutability 

ed avere il compilatore preclude qualcosa come:

object Hat extends Mutable with Immutable 

credo di poter forza qualche errore compilatore di avere un comune, membro contrastanti ma il messaggio di errore è un po 'obliqua:

trait Mutability 
trait Mutable extends Mutability { protected val conflict = true } 
trait Immutable extends Mutability { protected val conflict = true } 

object Hat extends Mutable with Immutable 

<console>:10: error: object Hat inherits conflicting members: 
value conflict in class Immutable$class of type Boolean and 
value conflict in class Mutable$class of type Boolean 
(Note: this can be resolved by declaring an override in object Hat.) 
    object Hat extends Immutable with Mutable 

Esiste un modo più diretto per esprimere questo vincolo e non permettere a qualcuno di aggirare il problema prendendo l'accenno offerto dal compilatore (sovrascrivere 'conflitto' in Hat)?

Grazie per eventuali approfondimenti

+0

Quale obiettivo raggiunge? Non riesco a ricordare in qualsiasi momento che abbia mai voluto fare questo .. – Daenyth

+0

Innanzitutto, grazie per le idee qui sotto, ancora rimuginando su se posso ottenere una soluzione ermetica (che non permette l'errore fin troppo facile " MutabilityLevel [Mutability] "per passare attraverso). Secondo, per quanto riguarda l'obiettivo. Ci sono due livelli di obiettivo: (1) tratto di marker per i gestori di segnale che possono tranquillamente non gestire eventi di aggiornamento per istanze di questo tipo e (2) estendere effettivamente il tratto Mutable per definire quegli eventi: class Events [T <: Mutable ] { case class Aggiungi (T) case class Rimuovi (T) } ad esempio. – jmcnulty

+0

'Mat classe (name: String) si estende Mutable' classe' Pat estende Immutable' gestori possono tranquillamente assumere che 'PatEvents oggetto si estende eventi [Pat]' non può compilare e 'PatEvents.Add/Remove' non esistono – jmcnulty

risposta

3

Penso che questo potrebbe funzionare

sealed trait Mutability 
case object Immutable extends Mutability 
case object Mutable extends Mutability 

trait MutabilityLevel[A <: Mutability] 

class Foo extends MutabilityLevel[Immutable.type] 

Questo (ab?) Utilizza il fatto che non è possibile estendere lo stesso tratto due volte con diversa parametrizzazione

scala> class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type] 
<console>:11: error: illegal inheritance; 
self-type Foo does not conform to MutabilityLevel[Immutable.type]'s selftype MutabilityLevel[Immutable.type] 
     class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type] 
         ^
<console>:11: error: illegal inheritance; 
self-type Foo does not conform to MutabilityLevel[Mutable.type]'s selftype MutabilityLevel[Mutable.type] 
     class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type] 

Tuttavia ..

scala> class Foo extends MutabilityLevel[Mutability] 
defined class Foo 
+0

È potrebbe risolvere ciò sigillando 'MutabilityLevel' e aggiungendo un altro livello, ad es 'tratto Immutable estende MutabilityLevel [MutabilityLevel.I]'. I chiamanti –

+0

@JCracknell potrebbero quindi estendere Immutable e fornire implementazioni improprie. – Daenyth

+0

Sì, tuttavia precluderebbe la creazione di un 'MutabilityLevel [Mutability]'. –

Problemi correlati