Reputation: 3739
Is it possible to implement it at compile time using Scala?
Use case:
Thing
s. ComplexThing
, he is not allowed to add anything elseIt's easy to check in runtime, and are there any solutions to implement it at compile time? The goal is to make IDE to highlight compile error.
trait Thing
trait SimpleThing extends Thing
trait ComplexThing extends Thing
sealed case class DummySimpleThing() extends SimpleThing
sealed case class InstanceOfComplexThing() extends ComplexThing
class ThingRepository {
private val buffer = new ListBuffer[Thing]()
def addThing(thing: Thing): ThingRepository = {
buffer += thing
this
}
}
object TestThingRepository {
def testAddThings() = {
new ThingRepository()
.addThing(DummySimpleThing())
.addThing(DummySimpleThing()) // it's ok to add SimpleThing after SimpleThing
.addThing(InstanceOfComplexThing()) // it's ok to add ComplexThing after SimpleThing
.addThing(DummySimpleThing()) // Not allowed to add anything after ComplexThing, how can I get compile time error here?
.addThing(InstanceOfComplexThing()) // Not allowed anything after ComplexThing, how can I get compile time error here?
}
}
Upvotes: 1
Views: 80
Reputation: 27421
You cannot do this with a mutable repository because you can't change the signature of a class once it is defined.
It would be possible to do this if addThing
returned a new repository, because adding ComplexThing
could return a repository without an addThing
method while adding SimpleThing
returns a repository with an addThing
method.
case class StaticThingRepository(buffer: List[Thing])
class ThingRepository private(buffer: List[Thing]) {
def addThing(thing: Thing): ThingRepository =
new ThingRepository(buffer :+ thing)
def addThing(thing: ComplexThing): StaticThingRepository =
StaticThingRepository(buffer :+ thing)
}
object ThingRepository {
def apply() = new ThingRepository(Nil)
}
Upvotes: 2