这段代码似乎设置了一个逆变的例子:FruitBox可以使用苹果或橘子。
class Fruit(name: String) { }
case class Apple(name: String) extends Fruit(name) {}
case class Orange(name: String) extends Fruit(name) {}
class Box[-T] {
type U >: T
def put(t: U): Unit= {box += t}
val box = scala.collection.mutable.ListBuffer[U]()
}
object test {
val FruitBox = new Box[Fruit]
// Fruit Box takes in everything
FruitBox.put(new Fruit("f1"))
FruitBox.put(new Orange("o1"))
FruitBox.put(new Apple("a1"))
// and Orange Box takes in only oranges
val OrangeBox = new Box[Orange]
//OrangeBox.put(new Apple("o2") ==> Compile Error that makes sense
OrangeBox.put(new Orange("o2"))
// Contra-variant nature is also demonstrated by
val o: Box[Orange] = FruitBox
}
这一切都很好......但为什么有效?特别: 1.当初始化FruitBox时,为什么"键入U>:T"不要将它限制在水果的超类型?尽管存在这种限制,FruitBox能够将子类型放入水果(橙子和苹果)......怎么样?
答案 0 :(得分:3)
首先,虽然Scala允许您编写new Box[Fruit]
,但U
是一个抽象成员,但我不明白为什么。 但是,在这种情况下,Scala似乎假设 Scala唯一知道的U = T
。由于您的代码从未实现U
,因此可以将其替换为T
。因此,您最终会在def put(t: Fruit)
中使用FruitBox
:当然它接受Apple
s,因为它们是Fruit
s!U
T
1}}它是T
的超类型;因此U
是T
的子类型,Fruit
的每个子类型也是如此。因此FruitBox.put
的任何子类型都可以传递给def put(t: U): Unit
。因此put(t: T): Unit
实际上与U
实际相同,除非您在new Box[Fruit] { type U = Object }
中实施class Box[T] {
def put(t: T): Unit= {box += t}
val box = scala.collection.mutable.ListBuffer[T]()
}
。
可以放苹果和橘子的FruitBox,以及只能放橙子的OrangeBox。这看起来像反变体行为,我很好。
并非所有逆变行为;你将与
完全一致render() {
return (
<div className="App">
<div className="App-header">
<h2>BAO BAO BAO</h2>
</div>
{this.state.result ? this.renderResult() : this.renderTest()}
<Baoquestion />
<AnswerChoices />
<BaoScore />
<Score />
</div>
);
}
export default App;
答案 1 :(得分:0)
为了补充@ AlexanderRomanov的答案,Scala将U >: T
视为存在类型_ >: T
。基本上,当您实际指定它时,它会实现为T
:
val orangeBox = new Box[Orange]
顺便说一句,另一种更常规的方法是在子类中实现U
:
trait Box[-T]{
type U >: T
}
class BoxImpl[T] extends Box[T]{
type U = T
}
因此,如果您使用类型参数而不是类型成员,则代码将类似于:
class Box[T, _ >: T]
val orangeBox = new Box[Orange, Orange]
在您的情况下,Scala会为您找到合适的类型,以便实现&#34;实现&#34;存在的。
这里唯一不一致的是它实际上不允许:
class BoxImpl[-T] extends Box[T]{
type U = T
}
//error: contravariant type T occurs in invariant position in type T of type U
所以基本上当您实例化Box[Orange]
时,它会忽略-T
class BoxImpl[T] extends Box[T]
中的Box
(无论原始-T
是否有data.submit();
)