A mia conoscenza, il modello di torta tradizionale di solito comporta 1 strato di nidificazione dei tratti, per raggruppare le operazioni. Quindi, il livello esterno dichiara il "servizio" effettivo (qui: Aggiungi, Mul, Operazioni) senza definirlo.
trait AddComponent[T] { this: FooComponent[T] =>
def addition: Add
trait Add {
def constant: T
def plus(t1: T, t2: T): T
def add(t: T) = plus(t, constant)
}
}
trait MulComponent[T] { this: BarComponent[T] =>
def multiplication: Mul
trait Mul {
def constant: T
def times(t1: T, t2: T): T
def mul(t: T) = times(t, constant)
}
}
trait OperationsComponent[T] { this: Add[T] with Mul[T] =>
def operations: Operations
trait Operations {
def neg(t: T): T
}
}
Poi, quando si mescolano i tratti "... Componente" insieme, le dipendenze sono cablati:
trait IntOperations extends Operation[Int] {
class IntAdd extends Add { ... }
class IntMul extends Mul { ... }
}
class MyFooBar extends FooComponent[Int] with BarComponent[Int] with IntOperations {
lazy val addition = new IntAdd
lazy val multiplication = new IntMul
lazy val foo = ...
lazy val bar = ...
}
Questo risolve il problema particolare namespacing ma si scontra nome (le definizioni di 'servizio') rimangono un problema del modello di torta tradizionale. C'è uno blog post di Daniel Spiewak che dimostra come può essere risolto in generale, ma la soluzione viene fornita con un proprio insieme di (enormi) compromessi (vedere this talk).
Spero che questo abbia aiutato un po '.
P.S. invece di digitare i parametri potrebbe essere meglio usare i tipi astratti qui
fonte
2013-05-13 10:41:22
Grazie per la risposta, risolve il mio problema. Per quanto riguarda il tuo PS, avrò anche conflitti di tipo nome se definisco il tipo astratto "T" in ogni tratto (dal momento che dovrebbe essere definito a livello "componente"). Ho sbagliato ? – paradigmatic
In questo caso particolare, "T" significa la stessa "cosa" in tutti i tratti, quindi non si scontreranno. Anche se ogni tratto contribuisce a una T con un tipo diverso legato, non si scontreranno, i loro limiti di tipo sono piuttosto raccolti insieme dai diversi tratti quando sono mescolati insieme. Finché i limiti non si scontrano, le cose vanno bene (per il compilatore). Questa è una cosa che Daniel Spiewak mostra in quel post del blog. Tuttavia, darei personalmente un tipo astratto sul livello "componente" un nome più descrittivo di "T", poiché 2 'T's non significa necessariamente la stessa cosa in 2 componenti diversi. –
OK. Ma qui ho bisogno di essere sicuro che i tipi siano unificati ('tipo T = Int 'ovunque), quindi ho bisogno di esprimere la dipendenza che tutti i tratti misti hanno lo stesso' T'. Non vedo come ottenerlo se non con tipi generici. – paradigmatic