I want to ask profies whether I can play around simultaneous application of cake pattern and stackable trait pattern?
Here is an example of the classical stackable traits pattern. I can use some FunnyModifier
s to change somehow behaviour in known way (for instance, for implementing aspect-oriented approach).
trait GeneralTrait {
def f: Int
}
class BaseImpl extends GeneralTrait {
override def f: Int = 5
}
class BaseImpl2 extends GeneralTrait {
override def f: Int = 50
}
trait FunnyModifier extends GeneralTrait {
abstract override def f: Int = super.f + 6
}
These definitions implies the following statements to be true:
(new BaseImpl).f == 5
(new BaseImpl with FunnyModifier).f == 11
(new BaseImpl2 with FunnyModifier).f == 56
But sometimes it can be desired to go with the cake pattern too (e.g. when no common trait exists for given bunch of implementations, only concrete class
structure), i.e. to write something like
class BaseImpl {
def f: Int = 5
}
class MoreImpl extends BaseImpl {
def u: String = "whatever functionality else"
}
trait FunnySubstitutor { self: BaseImpl =>
abstract override def f: Int = 6
}
This implementation actually works since FunnySubstitutor
fully substitutes the original function. But what if I want to modify the original behaviour, not only substitute? How can I address to actual parent’s implementation (i.e. an implementation of a class modifier (i.e. cake piece) is mixed with)?
trait BadFunnyModifier1 { self: BaseImpl =>
abstract override def f: Int = parent.f + 6 // Does not compile, parent has type AnyRef.
}
trait BadFunnyModifier2 { self: BaseImpl =>
abstract override def f: Int = parent[BaseImpl].f + 6 // Does not compile, parent is not BaseImpl yet.
}
trait BadFunnyModifier3 { self: BaseImpl =>
abstract override def f: Int = self.f + 6 // Compiles, but self.f call is virtual causing stack overflow.
}
For instance, why parent
cannot be thought as an inheritant of BaseImpl
in this case (so, making first two BadFunnyModifier
s to work)? This information is known at the compile time, as far as I can see.
So, is it possible somehow to make two wonderful patterns work together? I think it can be extremely useful for aspect-oriented-like addition of (originally) irrelevant functionality to the original functionality.