I have a problem on applying the cake pattern on my project. Here is the situation in a nutshell:
I have a trait Workflow which contains a type definition and another trait which can be added as a piece of the cake in a concrete Workflow.
trait VeryAbstractTrait
trait LessAbstractedTrait extends VeryAbstractTrait
class ConcreteImpl extends LessAbstractedTrait
class AnotherConcreteImpl extends VeryAbstractTrait
trait Workflow {
type T <: VeryAbstractTrait
}
trait AspectToBeAddedToWorkflow {
self: Workflow =>
type T <: LessAbstractedTrait
}
// Will compile ...
class ConcreteWorkflow extends Workflow with AspectToBeAddedToWorkflow {
final type T = ConcreteImpl
}
// Will not compile, since AnotherConcreteImpl is not type of LessAbstractedTrait
class AnotherConcreteWorkflow extends Workflow with AspectToBeAddedToWorklow {
final type T = AnotherConcreteImpl
}
In the previous example ConcreteWorkflow
compiles and AnotherConcreteWorkflow
not - As expected - Everything is fine.
But when I want to add some business logic to my trait AspectToBeAddedToWorkflow
which uses the type T
, the compiler tells me that T is still just an VeryAbstractTrait
and not LessAbstractedType
as I expected. To understand what I mean, have a look to the following snippet:
trait AspectToBeAddedToWorkflow {
self: Workflow =>
type T <: LessAbstractedTrait
val t: T
val a: VeryAbstractTrait = t // Compiles
val b: LessAbstractedTrait = t
/* Doesn't compile: type mismatch; found : AspectToBeAddedToWorkflow.this.T required: test.TraitSelftypes.LessAbstractedTrait */
}
It seems that the type T which is defined/ refined in the trait AspectToBeAddedToWorkflow
is not used as type for value t
- Even Eclipse jumps to Workflow
when pressing F3.
Can somebody explain this behaviour? Does someone have a clean solution for that problem (I know that I could extend Workflow instead of using a self type - But this destroys the cake pattern and has some other side effects which are not nice ...).
Thanks in advance! Michael
Edit 1:
To make it clear why I really need to have Workflow
as self type - In my program I want to use fields of Workflow
. Like shown below:
trait Workflow {
type T <: VeryAbstractTrait
val field: T
val anotherField: String
}
trait AspectToBeAddedToWorkflow {
self: Workflow =>
type T <: LessAbstractedTrait
val field: T // Now the type of field should be <: LessAbstractedTrait, but is still <: VeryAbstractTrait
def anything = {
println(anotherField)
}
}
And I don't really want to extend AspectToBeAddedToWorkflow
with Workflow
since this would destroy the really nice cake pattern we applied ...