Reputation: 21220
Suppose I have the following:
abstract class Service {}
case class Blue() extends Service
case class Green() extends Service
case class Red() extends Service
abstract trait Material {
def supports(s: Service): Service
}
trait Wood extends Material {
def supports(s: Service): Boolean = {
s match {
case _:Blue => false
case _:Green => true
case _ => false
}
}
}
trait Stone extends Material {
def supports(s: Service): Boolean = {
s match {
case _:Blue => true
case _:Green => false
case _ => false
}
}
}
Now, what I want to do is have a type MyService
that is both Stone
and Wood
, such that MyService.supports(service)
will return true
if service
is either Blue
or Green
, but false
if it is Red
:
case class MyService() extends Wood with Stone
service = new MyService()
service.supports(new Blue()) //true
service.supports(new Green()) //true
service.supports(new Red()) //false
Obviously the above creates a conflict because both Wood
and Stone
implement the same method. I could create a new trait StoneAndWood
, but that seems inelegant. Is there an elegant way of merging those two functions (essentially putting a boolean or
between them?). Would a different class design make this task easier?
Upvotes: 3
Views: 196
Reputation: 9901
How about having each subclass of Material
call its superclass's supports
method if it doesn't support the service? Something like this:
abstract trait Material {
def supports (s: Service) = false
}
trait Wood extends Material {
override def supports (s: Service) =
s match {
case _: Green => True;
case _ => super supports s
}
}
trait Stone extends Material {
override def supports (s: Service) =
s match {
case _: Blue => True;
case _ => super supports s
}
}
Upvotes: 1
Reputation: 3760
You can do something like this
class WoodStone extends Wood with Stone {
override def supports(s: Service): Boolean = {
super[Wood].supports(s) || super[Stone].supports(s)
}
}
Upvotes: 0