我一直在关注一些在线教程以学习Scala。我遇到了以下代码段:
class Holder[+T](val value: T) {
def printIt = println(value)
}
val h1 = new Holder(3)
h1.printIt
class Person
class Employee extends Person
val h2 = new Holder(new Employee)
val h3 : Holder[Person] = h2
不幸的是,老师没有解释val h3
表达式对:
冒号的影响。有人可以开导我吗?
答案 0 :(得分:2)
这是一个类型Annotation,Scala可以自动找出变量的类型(称为类型推断),这就是刚刚使用val h3
时会发生的情况。但是如果需要,您可以明确指定类型。所以val h3: Holder[Person]
表示值h3
的类型为Holder[Person]
出于几个原因,您可能希望这样做。第一个是文档。如果指定类型,则清除变量或方法的类型,因此您无需考虑它。如果您不小心犯了错误并尝试将错误的类型放入变量中,它也会导致错误。通常,像本地和私有成员这样的东西没有必要用类型注释来混淆代码,但是将它们包含在任何公共字段或方法中是个好主意。
另一个原因是因为你想要一种不同于推理所确定的类型是合适的。通常(如示例中的情况),这是因为您要分配的实际对象是您希望方法或变量所需类型的子类型。在示例中,h2
的类型为Holder[Employee]
,因此Scala也会为h3
推断出类型,但我们希望h3
的类型为超类型,{ {1}}所以我们明确地包含了类型注释。
答案 1 :(得分:1)
val h3 : Holder[Person] = h2
上面定义了一个名为h3
的值,并为其指定了h2
个实例。 :
明确指出值h3
的类型为Holder[Person]
。如果遗漏: Holder[Person]
部分,编译器会将h3
的类型推断为Holder[Employee]
(因为h2
是Holder[Employee]
)。
h3
可以正确地称为Holder[Person]
或Holder[Employee]
。这是因为Holder
具有协变类型参数(+T
),这意味着由于Employee
是Person
的子类型,Holder[Employee]
是Holder[Person]
的子类型1}}。
答案 2 :(得分:0)
+ T声明Holder是协变的,因此Holder [Person]类型的持有者是Holder [Employee]类型持有者的超类。在该行中,您只需声明h3的类型是Holder [Person]。由于协方差,您可以将持有人[员工]分配给持有人[人员]。