在我工作的公司中,我们从(Java)模式中获得了很多好处,可以总结如下:
我们可以通过他们的特殊/智能“id”来获取一些“东西”。每个“事物”都知道它的 id,而 id 是“智能”的,因为您可以要求它们向您提供它们识别的“事物”。在复杂且不断增长的“事物”层次结构中,这简化了维护并消除了大量代码(重复和其他代码)。我确信你们中的一些人可能会觉得这很奇怪,我可以解释为什么会这样,但事实是它是这样的,到目前为止它很有帮助,并且不是问题的一部分。
Java 定义总结如下(稍作重写):
interface Id<I extends Id<I,T>, T extends Thing<I,T>> {
T getThing();
...
}
interface Thing<I extends Id<I,T>, T extends Thing<I,T>> {
public I getId();
...
}
有时,我们需要在给定一批不同 ID 的情况下获取“一批”事物(这会跨网络,因此通过批处理来加快速度)。为了描述的目的,它可以写成:
public Map<Id<?,?>,Thing<?,?>> getManyThings(List<Id<?,?>> idsToGetThingsFor);
(方法参数只是多个 id,它是集合、列表还是其他形式并不重要)
现在,在网络的另一端,这个方法在 Scala 2.9 中实现,相当难看地避免了 Scala 泛型的严格性。我们正在尝试升级到 Scala 2.10,但事情不再编译,必须找到一种方法来处理这个问题。诀窍是有一个Scala方法总结如下:
def getOneThing[I <: Id[I,T],T <: Thing[I,T]](id: I): T;
该方法根据许多因素适本地检查、处理和分配调用 - 此处解释太多且无关紧要。
现在, getManyThings() 方法会迭代传递给它的 id,并且需要将它们作为参数传递给 getOneThing()。这就是事情失败的地方。 getManyThings() 只知道它获取的 id 本质上是 Id[,],Scala 提示 [,] 对于 [I <: Id[I,T] 来说不够好],T <: Thing[I,T]] getOneThing() 需要:
... error: inferred type arguments [Id[_$16,_$17],Nothing] do not conform to method getOneThing's type parameter bounds [I <: Id[I,T],T <: Thing[I,T]]
注意 - 为 Id 和 Thing 声明非参数化(非泛型)基类并没有真正的帮助,因为它只会将问题推向(太多)其他地方。我们选择非常严格的类型来确保代码质量,但我们确实必须有一种方法来处理“混合”集合。
有什么帮助吗?请!
最佳答案
我假设你有这样的方法:
def getManyThings[I <: Id[I, T], T <: Thing[I, T]](ids:List[I]):List[T] =
ids map getOneThing
这会产生错误,因为编译器无法推断您想要使用 T
作为第二个类型参数来调用 getOneThing
方法。
为了“帮助”编译器,您需要显式传递它们:
trait Id[I <: Id[I, T], T <: Thing[I, T]]
trait Thing[I <: Id[I, T], T <: Thing[I, T]]
def getOneThing[I <: Id[I, T], T <: Thing[I, T]](id:I):T = ???
def getManyThings[I <: Id[I, T], T <: Thing[I, T]](ids:List[I]):List[T] =
ids map ( getOneThing[I, T](_) )
关于scala - 在 Scala 2.10 中使用混合复杂 Java 泛型集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16122154/