我正在尝试定义一个方法 - 它接受A
,它必须是2个特征的子类型。
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
如何正确撰写f
,使其仅接受Foo
和Bar
的实施者?
答案 0 :(得分:2)
您可以使用复合类型来执行此操作。
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
相同的语法可以与类型参数一起使用,但我在这里没有看到它。
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
你可以写的另一种方式是:
def f[A](a: A with Foo with Bar) = ...