我想编写一个采用嵌套类型的泛型类。外部类型(I
)必须扩展Iterable,内部类型(M
)可以是任何东西。
以下是我的例子:
// The outer type here is I and the inner type is M
class GenericDistributor[I <: Iterable[M], M] {
def map(input: I): Unit = {
input.foreach(item => {
//do some stuff
})
}
}
class IntegerGroup(id: Int, items: Set[Int]) extends Iterable[Int] {
override def iterator: Iterator[Int] = items.iterator
}
object IntegerGroupDistributor extends GenericDistributor[IntegerGroup, Int]
val integerGroup = new IntegerGroup(1, Set(1,2,3))
IntegerGroupDistributor.map(integerGroup)
问题是我必须在GenericDistributor类中明确定义内部类型M,这是我不想要的。在给定外部类型的情况下,Scala有没有办法自动推断内部类型?
编辑
根据@Arioch的评论。我试过鸭子类型,这似乎解决了我的问题,但我觉得应该有更简洁的方式。
class GenericDistributor[I <: {type M; def iterator: Iterator[M]}] {
def map(input: I): Unit = {
val it: Iterator[M] = input.iterator
it.foreach(println)
}
}
class IntegerGroup(id: Int, items: Set[Int]) extends Iterable[Int] {
type M = Int
override def iterator: Iterator[Int] = items.iterator
}
object IntegerGroupDistributor extends GenericDistributor[IntegerGroup]
答案 0 :(得分:2)
如果您不需要使用I
类型的任何自定义方法,则只需在M
上参数化您的外部类。 Iterator[M]
不需要单独添加,因为您已经拥有了从M
定义它所需的全部内容。
class GenericDistributor[M] {
type I = Iterable[M]
def map(input: I): Unit = {
input.foreach(item => {
//do some stuff
})
}
}
答案 1 :(得分:2)
如果您只想要一个类型参数,则有两个选项:
(1)说明你不关心迭代器的类型
class GenericDistributor[I <: Iterable[_]]
(2)使用隐式存储内部类型
class GenericDistributor[I : IterableInfo]
// or (equivalently)
class GenericDistributor[I]()(implicit i: IterableInfo[I])
trait IterableInfo[I] {
type Element
}
object IterableInfo {
implicit def forIterable[I <: Iterable[M], M]: IterableInfo[I] { type Element = M } = ...
}
最后一个选项允许您以多种不同方式塑造代码。您可以向IterableInfo
添加方法,可以添加type
个成员,可以在Iterable
类型参数中添加I
限制。