Reputation: 41909
I'm trying to define a method - it accepts an A
, which must be a sub-type of 2 traits.
scala> trait Foo
defined trait Foo
scala> trait Bar
defined trait Bar
scala> def f[A <: Foo, Bar](x: A) = x
f: [A <: Foo, Bar](x: A)A
scala> case class Bip extends Foo with Bar
scala> val bip = Bip()
bip: Bip = Bip()
// looks good
scala> f(bip)
res0: Bip = Bip()
// only extends `Foo`
scala> case object Fip extends Foo
defined module Fip
// I expected a compile-time error
scala> f(Fip)
res1: Fip.type = Fip
How can I properly write f
such that it only accepts an implementor of Foo
and Bar
?
Upvotes: 1
Views: 103
Reputation: 55569
You can use compound types to do this.
trait Foo
trait Bar
def f(a: Foo with Bar) = ???
scala> val foobar = new Foo with Bar
foobar: Foo with Bar = $anon$1@1b8c25c0
scala> f(foobar) // Happily accepts a class that mixes Foo and Bar
res26: Foo with Bar = $anon$1@1b8c25c0
scala> f(new Foo{}) // Refuses a class that only mixes Foo
<console>:23: error: type mismatch;
found : Foo(in object $iw)
required: Foo(in object $iw) with Bar
The same syntax can be used with a type parameter, though I don't see it as necessary here.
def f[A <: Foo with Bar](a: A) = a
scala> f(foobar) // Accepts a class that mixes Foo and Bar
res29: Foo with Bar = $anon$1@1b8c25c0
scala> f(new Foo{}) // Refuses a class with only Foo, as it breaks the type bounds
<console>:25: error: inferred type arguments [Foo] do not conform to method f's type parameter bounds [A <: Foo with Bar]
<console>:25: error: type mismatch;
found : Foo
required: A
Another way you could write it is:
def f[A](a: A with Foo with Bar) = ...
Upvotes: 2