I'm working on something in work that I want to generalize over (some behavior that repeats exactly in several classes but for different concrete types [called it C, see bellow] ) with some restrictions of some interfaces(traits) in order be able to use some of the behaviors of those interfaces that are common between all the concrete types (Sound very abstract and general.. the best way to explain my problem is to look at the code).
I simplified the real code with a similar structure just to demonstrate the problem
package playground
object Conformance {
trait S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS() extends S
final case class ConcreteG() extends G
final class C1 extends RT[ConcreteS, ConcreteG] {
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C2 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//some different impl
final class C3 extends RT[ConcreteS, ConcreteG]{
override def getS: ConcreteS = ConcreteS()
override def getG: ConcreteG = ConcreteG()
}
//generic impl over W
trait GeneralizationOverW[C <: RT[S, G]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[C1]
class W2 extends GeneralizationOverW[C2]
class W3 extends GeneralizationOverW[C3]
}
Imagine that C1,C2,C3
have different implementations (which are code generated), and I tried to generalize over the W's using different C's with GeneralizationOverW
I tried to read about compound types in Scala spec, but could not figure out why I get the following compile error and how to fix it:
type arguments [playground.Conformance.C1] do not conform to trait GeneralizationOverW's type parameter bounds [C <: playground.Conformance.RT[playground.Conformance.S,playground.Conformance.G]] class W1 extends GeneralizationOverW[C1]
Edited: updated code after suggestion:
package playground
object Conformance {
trait S
trait SS extends S
trait G
trait R {
type ST <: S
type GT <: G
def getS: ST
def getG: GT
}
trait RT[SD <: S, GD <: G] extends R {
override type ST = SD
override type GT = GD
}
final case class ConcreteS1() extends SS
final case class ConcreteS2() extends SS
final case class ConcreteS3() extends SS
final case class ConcreteG1() extends G
final case class ConcreteG2() extends G
final case class ConcreteG3() extends G
final class C1 extends RT[ConcreteS1, ConcreteG1] {
override def getS: ConcreteS1 = ConcreteS1()
override def getG: ConcreteG1 = ConcreteG1()
}
//some different impl
final class C2 extends RT[ConcreteS2, ConcreteG2]{
override def getS: ConcreteS2 = ConcreteS2()
override def getG: ConcreteG2 = ConcreteG2()
}
//some different impl
final class C3 extends RT[ConcreteS3, ConcreteG3]{
override def getS: ConcreteS3 = ConcreteS3()
override def getG: ConcreteG3 = ConcreteG3()
}
//generic impl over W
trait GeneralizationOverW[ST <: S,GT <: G , CON <: RT[ST, GT]] {
// With `<: RT[S, G]` restriction I know C is RT with some S and G I can use S and G behaviours
}
class W1 extends GeneralizationOverW[ConcreteS1,ConcreteG1,C1]
class W2 extends GeneralizationOverW[ConcreteS2,ConcreteG2,C2]
class W3 extends GeneralizationOverW[ConcreteS3,ConcreteG3,C3]
}
I think it works now :)