2015-02-10 60 views
1

我试图定义一个方法 - 它接受一个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

我只想澄清一点,'高清F [A <:美孚,酒吧] ...'并不意味着你认为它手段。它像“(A <:Foo),Bar”一样分组。换句话说,你正在创建另一个名为'Bar'的类型变量,它隐藏了特性'Bar'。 – ephemient 2015-02-10 22:03:51

回答

2

您可以使用复合类型来执行此操作。

trait Foo 
trait Bar 
def f(a: Foo with Bar) = ??? 

scala> val foobar = new Foo with Bar 
foobar: Foo with Bar = [email protected] 

scala> f(foobar) // Happily accepts a class that mixes Foo and Bar 
res26: Foo with Bar = [email protected] 

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 = [email protected] 

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) = ... 
+0

如果'Foo'是一个case类,'Bar'仍然是一个特征,是否需要'A <:Foo with Bar'? – 2015-02-10 19:42:59

+0

我不确定你的意思。 'Foo'是一个混合在'Bar'中的类吗?如果你想'A'既是'Foo'又是'Bar',那么'A <:Foo with Bar'仍然是必需的。他们不需要成为特质。例如,你可以有'A <:Int with Bar'。 – 2015-02-10 19:57:39

+0

尽管我没有看到类型参数。复合参数工作得很好。 – 2015-02-10 20:16:01

相关问题