1

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 AnotherConcreteWorkflownot - 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 ...

cokeSchlumpf
  • 163
  • 1
  • 9

1 Answers1

0

Thanks to you som-snytt - https://stackoverflow.com/a/10223364/1296806 This is indeed the right answer to the question.

Community
  • 1
  • 1
cokeSchlumpf
  • 163
  • 1
  • 9