假设我们在下面有代码段
trait Foo
class Bar extends Foo
def foobar(fn: Option[Set[_ <: Foo] => Unit]) {}
def main(args: Array[String]) {
foobar(Option(bar)) //doesnt compile
}
def bar(input: Set[Bar]) {}
它进行编译,因为函数1被定义为trait Function1 [-T1, +R] extends AnyRef
。我的问题无论如何在Scala中编写一个函数,它接受一个Type T或它的子类型并做一些事情?或者我害怕它不可能
答案 0 :(得分:3)
您可以将Set
中的foobar
的类型约束移到函数本身的类型参数上:
trait Foo {
class Bar extends Foo
def foobar[A <: Foo](fn: Option[Set[A] => Unit]) {}
def main(args: Array[String]) {
foobar(Option(bar _)) //compiles!
}
def bar(input: Set[Bar]) {}
}
Scala编译器将从传递给A
的参数中推断出类型foobar
,同时仍然强制执行类型约束。此外,您需要部分应用bar
将Option
传递给它。
答案 1 :(得分:1)
怎么样
trait Foo
class Bar extends Foo
def bar(input: Set[_ <: Foo]) {}
def foobar(fn: Option[Set[_ <: Foo] => Unit]) {}
foobar(Some(bar(_))) // partially applied
foobar(None)
您现在可以执行类似这样的操作,在某些情况下完全应用foobar()
val x = Set(new Bar())
foobar(Some( x => bar(x)))
请注意,必须是x =&gt; bar(x)因为类型是一些函数对象,而不是函数的结果。
答案 2 :(得分:1)
如果你想使用存在而不是Jesse的回答,你可能会有类似的东西:
def foobar(fn: Option[(Set[X] => Unit) forSome { type X <: Foo }]) {}
foobar(Option(bar _))