继这个问题之后,有人可以在Scala中解释以下内容:
class Slot[+T] (var some: T) {
// DOES NOT COMPILE
// "COVARIANT parameter in CONTRAVARIANT position"
}
Run Code Online (Sandbox Code Playgroud)
我明白之间的区别+T,并T在类型声明(它编译如果我使用T).但是,如何实际编写一个在其类型参数中具有协变性的类而不依赖于创建未参数化的东西?如何确保只能使用实例创建以下内容T?
class Slot[+T] (var some: Object){
def get() = { some.asInstanceOf[T] }
}
Run Code Online (Sandbox Code Playgroud)
编辑 - 现在得到以下内容:
abstract class _Slot[+T, V <: T] (var some: V) {
def getT() = { some }
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但我现在有两个类型参数,我只想要一个.我会再问这个问题:
如何编写一个在其类型中具有协变性的不可变 Slot类?
编辑2:呃!我用过var而不是val.以下是我想要的:
class Slot[+T] (val some: …Run Code Online (Sandbox Code Playgroud) 在 Scala 应用程序中进行重构时,我遇到了从 List 更改为 Set 提出了一个我以前没有的问题的情况。我对方差有一些想法,但我想了解它对编译器究竟意味着什么。
我有类似的东西,它编译和工作得很好:
case class MyClassList(s: List[Any])
val myList = List(("this", false)) // List[(String, Boolean)]
val listWorks = MyClassList(myList)
Run Code Online (Sandbox Code Playgroud)
然后我更改了我的列表以设置:
case class MyClassSet(s: Set[Any])
val mySet = Set(("this", false)) // Set[(String, Boolean)]
val setFails = MyClassSet(mySet)
Run Code Online (Sandbox Code Playgroud)
在这一点上,创建一个 MyClassSet 类型的对象不再适合我传递一个 Set 作为参数,即使它接受一个 Set of Any。现在,当以下工作时它有点混乱(请注意,该集合与之前的 mySet 是“相同的”):
val setWorks1 = MyClassSet(Set(("this", false)))
Run Code Online (Sandbox Code Playgroud)
我相信简单的解释是编译器将 mySet val 推断为 Set[(String, Boolean)],但是当我直接在 setWorks1 的参数列表中实例化它时,因为它接受一个 Set[Any],编译器是将其推断为 Set[Any]。这使得第一个示例失败而第二个通过。这些也有效,这表明前一个是正确的:
val setWorks2 = MyClassSet(mySet.toSet[Any])
val mySetOfAny: Set[Any] = Set(("this", false), ("that", true), ("other", false)) …Run Code Online (Sandbox Code Playgroud)