实现两个特征的通用方法

时间:2015-02-10 19:35:10

标签: scala

我正在尝试定义一个方法 - 它接受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,使其仅接受FooBar的实施者?

1 个答案:

答案 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) = ...