我想用 mutable.HashMap[] 的 val 扩展一个类,如下所示:
class Father
class Son extends Father
class C1{
val m = new mutable.HashMap[Int, Father]()
}
class C2 extends C1{
override val m = new mutable.HashMap[Int, Son]()
}
Run Code Online (Sandbox Code Playgroud)
并得到一个错误:
错误:(19, 16) 覆盖类型为 scala.collection.mutable.HashMap[Int,ScalaByExample.Father] 的类 C1 中的值 m;值 m 具有不兼容的类型覆盖 val m = new mutable.HashMapInt, Son
我发现它immutable.HashMap是协变的,但它mutable.HashMap是不变的。如果替换mutable.HashMap为immutable.HashMap.
所以我的两个问题是:
如何使用 mutable.HashMap 使其工作?
为什么scala的作者要这样设计HashMap?
我从斯卡拉看到层次即AnyVal是超级类型scala.Unit,Boolean,Char和其他Number类型.
scala> val list1 = List((), 1 )
list: List[AnyVal] = List((), 1) // I see this is valid when compared with hierarchy tree.
scala> val list2 = List(Unit, 1 )
list: List[Any] = List(object scala.Unit, 1) // Why???
Run Code Online (Sandbox Code Playgroud)
我看到的list1是型AnyVal,其中作为list2是类型的Any,即使它们具有相同的数据(我假设).
是()不是一样的Scala.Unit?我在这里错过了什么?
这可能吗?如果没有,为什么这不可能在Java?
interface B extends A {}
public List<B> getList();
List<A> = getList(); // Type mismatch: cannot convert from List<B> to List<A>
Run Code Online (Sandbox Code Playgroud)
是不是Java中String的子类型Object?
那么,为什么我不能将类型的对象传递List<String>给接受List<Object>作为参数的函数?但是,我可以将这样的对象传递给一个接受List作为参数的函数.
应用@tailrec我从scala编译器得到错误:"无法优化@tailrec注释方法get:它包含一个目标为超类型case = => tail.get(n-1)的递归调用".有人可以解释为什么会这样吗?
trait List[T] {
def isEmpty: Boolean
def head: T
def tail: List[T]
def get(n: Int): T
}
class Cons[T](val head: T, val tail: List[T]) extends List[T]{
def isEmpty = false
@tailrec
final def get(n: Int) =
n match {
case 0 => head
case _ => tail.get(n-1)
}
}
class Nil[T] extends List[T]{
def isEmpty = true
def head = throw new NoSuchElementException("Nil.head")
def tail = throw new NoSuchElementException("Nil.tail")
final def get(n: Int): T = throw …Run Code Online (Sandbox Code Playgroud) 我正在阅读"Scala in depth"的第一部分,第一部分有两个关于"covariance"和"contrvariance"的句子:
协方差(+ T或?extends T)是指类型可以在继承层次结构中强制转换.
逆变量(-T或?super T)是指类型可以强制继承层次结构.
我已经阅读了一些关于"协方差"和"逆变"的文件,但在这种背景下我无法理解"强迫"和"强迫"这个词.
查看List.scala的源代码:
sealed abstract class List[+A] extends ...
...
def isEmpty: Boolean
def head: A
def tail: List[A]
Run Code Online (Sandbox Code Playgroud)
List[+A]是基于的协变+A.这是否意味着,可以创建一个List[T]T可以是类型本身或其任何子类?
例:
scala> trait Kid
defined trait Kid
scala> case class Boy(name: String) extends Kid
defined class Boy
scala> case class Girl(name: String) extends Kid
defined class Girl
scala> val list: List[Kid] = List(Boy("kevin"), Girl("sally"))
list: List[Kid] = List(Boy(kevin), Girl(sally))
Run Code Online (Sandbox Code Playgroud)
分别观察head和tail类型是A和List[A].一旦我们定义了List[+A],那么head和tail …
在Scala中,许多类型都扩展了Any.单击此处查看Scala类层次结构图.
例如,Double和Tuple都扩展了Any,下面的代码按预期工作:
def foo(x: Any) { println(x.toString) }
foo(3.0) // prints: 3.0
foo((2,3)) //prints: (2,3)
Run Code Online (Sandbox Code Playgroud)
但是,我不明白为什么以下不起作用,因为它遵循以上所有逻辑:
def bar(fn: Any => String) { println(fn.toString) }
def dub(d: Double): String = "dub"
def tup(tup: (Int, Int)): String = "tup"
bar(dub) // ERROR
bar(tup) // ERROR
Run Code Online (Sandbox Code Playgroud)
调用bar(dub)和bar(tup)都会导致类型不匹配错误.对于bar(dub),编译器说:
error: type mismatch;
found: Double => String
required: Any => String
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么在第二种情况下存在类型不匹配,即使Any是超类型吗?
sealed trait List[+A] // `List` data type, parameterized on a type, `A`
case object Nil extends List[Nothing] // A `List` data constructor representing the empty list
/* Another data constructor, representing nonempty lists. Note that `tail` is another `List[A]`,
which may be `Nil` or another `Cons`.
*/
case class Cons[+A](head: A, tail: List[A]) extends List[A]
Run Code Online (Sandbox Code Playgroud)
我的问题是A前面的“+”是什么?为什么在这里“List[A]”加号被忽略了?
谢谢