协调多个通用构造函数参数

时间:2013-02-13 00:05:05

标签: scala generics types

我正在尝试在Scala中做一些我不确定的事情。我很喜欢社区的一些反馈。

说我对某些'东西'有一个密封的特性,它的一些具体扩展,以及一个与该特征的某些实现一起工作的泛型类。

sealed trait Thing
class CoolThing extends Thing
class OtherThing extends Thing

class BoxOfThings[T <: Thing]

现在,我可以定义另一个处理两个“盒子”的类,如此......

class PairOfBoxes(boxOne: BoxOfThings[_ <: Thing], boxTwo: BoxOfThings[_ <: Thing])

但是,在这里创建PairOfBoxes并使用一个CoolThing s和另一个OtherThing s完全没问题。我想声明boxOneboxTwo包含相同类型的Thing ..是否尽可能?

例如:

// Cool things..
val boxOfCoolThings = new BoxOfThings[CoolThing]
val anotherBoxOfCoolThings = new BoxOfThings[CoolThing]
// Other things..
val boxOfOtherThings = new BoxOfThings[OtherThing]

// A pair of cool boxes, no problem:
new PairOfBoxes(boxOfCoolThings, anotherBoxOfCoolThings)

// A pair of different boxes, compiles but I don't want it to:
new PairOfBoxes(boxOfOtherThings, anotherBoxOfCoolThings)

我可以通过制作PairOfBoxes通用本身来做到这一点,就像这样......

class TypedPairOfBoxes[T <: BoxOfThings[_ <: Thing]](boxOne: T, boxTwo: T)

它有效,但它很丑..

// A pair of cool boxes, no problem:
new TypedPairOfBoxes[BoxOfThings[CoolThing]](boxOfCoolThings, anotherBoxOfCoolThings)

// A pair of different boxes, doesn't compile:
val mixedPair = new TypedPairOfBoxes[BoxOfThings[CoolThing]](boxOfOtherThings, anotherBoxOfCoolThings)

我想避免这是我可以。它将问题推向上游并迫使我们指定每个TypedPairOfBoxes的内容。简单地使用无类型的PairOfBoxes是理想的,它声明它的参数属于同一类型。

可能的?

谢谢!

2 个答案:

答案 0 :(得分:1)

你只需要写为:

class TypedPairOfBoxes[T <: Thing](one: BoxOfThings[T], two: BoxOfThings[T])

然后:

scala> new TypedPairOfBoxes(boxOfOtherThings, anotherBoxOfCoolThings)
<console>:15: error: type mismatch;
 found   : BoxOfThings[OtherThing]
 required: BoxOfThings[Thing]
Note: OtherThing <: Thing, but class BoxOfThings is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
              new TypedPairOfBoxes(boxOfOtherThings, anotherBoxOfCoolThings)
                                   ^
<console>:15: error: type mismatch;
 found   : BoxOfThings[CoolThing]
 required: BoxOfThings[Thing]
Note: CoolThing <: Thing, but class BoxOfThings is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
              new TypedPairOfBoxes(boxOfOtherThings, anotherBoxOfCoolThings)
                                                     ^

scala> new TypedPairOfBoxes(boxOfCoolThings, anotherBoxOfCoolThings)
res3: TypedPairOfBoxes[CoolThing] = TypedPairOfBoxes@2f5e1167

答案 1 :(得分:0)

我&lt; 3 Scala

Scala可以推断出泛型类型,这样我就可以定义一个“丑陋”的类型,但在使用它时不需要指定具体的实现。

通过这种实现,我能够定义类似于上面问题中的类型的类型。

class TypedPairOfBoxes[T, BoxOfThings[T <: Thing]](boxOne: BoxOfThings[T], boxTwo: BoxOfThings[T])

..它看起来有点粗糙,但可以像这样使用:

// Both boxes contain cool things, no problem:
new TypedPairOfBoxes(boxOfCoolThings, anotherBoxOfCoolThing)

// These boxes contain different things, doesn't compile:
new TypedPairOfBoxes(boxOfOtherThings, anotherBoxOfCoolThing)

惊人的。

修改

正如@Eastsun所证明的那样,通用定义的后半部分未被使用。所以可以写成:

class TypedPairOfBoxes[T <: Thing](boxOne: BoxOfThings[T], boxTwo: BoxOfThings[T])

这看起来非常像Java。但令人惊奇的是,Scala从参数中推断出泛型类型。