trait Base {
type S <: BaseState
trait BaseState {
def base: String
}
var state: S
}
trait ExtensionA {
this: Base =>
// here I want to restrict that S must be subtype of ExtensionAState whenever this trait is mixed-in
type S <: ExtensionAState
trait ExtensionAState {
def extensionA: String
}
// this line does not compile
// I want this to be typesafe because state should be subtype both of BaseState and ExtensionAState
def extensionMethod() = state.base + state.extensionA
}
class Final extends Base with ExtensionA {
type S = State
var state = State("base", "extension")
case class State(base: String, extensionA: String) extends BaseState with ExtensionAState
}
object Test extends App {
println(new Final().extensionMethod())
}
trait Base {
type S <: BaseState
trait BaseState {
def base: String
}
var state: S
}
/**
* Extends base trait with extensionA state property and extensionAMethod which can use state with both BaseState's
* and ExtensionAState's properties
*/
trait ExtensionA extends Base {
type S <: BaseState with ExtensionAState
trait ExtensionAState {
def extensionA: String
}
def extensionAMethod() = state.base + state.extensionA
}
/**
* Extends base trait with extensionB state property and extensionBMethod which can use state with both BaseState's
* and ExtensionBState's properties
*/
trait ExtensionB extends Base {
type S <: BaseState with ExtensionBState
trait ExtensionBState {
def extensionB: String
}
def extensionBMethod() = state.base + state.extensionB
}
/**
* Extends base trait with extensionC state property and extensionCMethod and define dependency to both
* ExtensionA and ExtensionB, so the method extensionCMethod can use all state properties
*/
trait ExtensionC extends Base with ExtensionA with ExtensionB {
type S <: BaseState with ExtensionAState with ExtensionBState with ExtensionCState
trait ExtensionCState {
def extensionC: String
}
def extensionCMethod() = state.base + state.extensionA + state.extensionB + state.extensionC
}
class Final extends Base with ExtensionA with ExtensionB with ExtensionC {
type S = State
var state = State("base", "extensionA", "extensionB", "extensionC")
case class State(base: String,
extensionA: String,
extensionB: String,
extensionC: String) extends BaseState with ExtensionAState with ExtensionBState with ExtensionCState
}
object Test extends App {
val obj = new Final()
println(obj.extensionAMethod())
println(obj.extensionBMethod())
println(obj.extensionCMethod())
}