0

我正在尝试在 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用一个CoolThings 和另一个OtherThings 来创建 a 是完全可以的。我想声明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断言它的参数是相同类型的无类型是理想的。

可能的?

谢谢!

4

2 回答 2

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
于 2013-02-13T03:10:56.140 回答
0

我 <3 斯卡拉

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 从参数中推断出泛型类型。

于 2013-02-13T00:26:44.327 回答