为啥 Scala 语言要求您初始化实例变量而不是依赖默认值?
Posted
技术标签:
【中文标题】为啥 Scala 语言要求您初始化实例变量而不是依赖默认值?【英文标题】:Why does Scala language require you initialize a instance variable instead of relying on a default value?为什么 Scala 语言要求您初始化实例变量而不是依赖默认值? 【发布时间】:2011-11-09 14:36:05 【问题描述】:Scala 语言要求您在使用实例变量之前对其进行初始化。但是,Scala 没有为您的变量提供默认值。相反,您必须使用通配符下划线手动设置其值,它的作用类似于默认值,如下所示
var name:String = _
我知道,我知道...我可以在类定义中定义一个构造函数,它将我们的实例变量作为参数,因此 Scala 不会强制其初始化,如下所示
class Person(var name:String)
但是,我需要在正文中声明它,因为我需要使用 ElementType 为 FIELD 或 METHOD 的 Java 注释;也就是说,它可以只应用于我们类主体中声明的实例变量或方法。
问题:为什么 Scala 语言要求你初始化一个实例变量——无论是默认值 _ 还是你想要的——在类的主体中声明而不是依赖默认值?
【问题讨论】:
Martin 的偏好是我的猜测 :-) 至少它是明确的,额外的 2 个字符(4 个带空格)并不是非常令人生畏。 Java(一种非常冗长的语言)让赋值被省略似乎有点愚蠢。此外,说“构造函数参数”(不知道它们的真正名称是什么:-/)似乎是误导性的——它们肯定是在对象被实例化时。 【参考方案1】:如果您使用如下代码声明,name
应该是抽象的:
class A
var name: String
我想你已经知道了。所以你的问题是句法性质的。 答案是与其他可能的抽象候选者保持一致。
假设你想做这样的事情:
class A
var variable: String = _ // variable has some default value (probably null)
val value: String = _ // value cannot have any default values, since it cannot be reassigned later.
def method: String = _ // method could return some default value (probably null)
type theType = _ // what should the default type be? (Any perhaps?)
最后三个示例甚至无法编译。现在假设你想做这样的事情:
class A
var variable: String
val value: String
def method: String
type theType
在我看来,即使是几乎不了解 Scala 的人只看到声明。没有办法曲解它们,因为除了声明之外别无他物。当您来自另一种语言并假设有一些默认值时,会出现唯一的混淆。但是,当您看到第一个示例(具有默认值的示例)时,这种混淆就消失了。顺便说一句,您的类必须是抽象层次结构的一部分才能被允许声明抽象成员,因此即使您是该语言的新手,您也已经从编译器获得了一些额外的帮助。
我希望这能回答您的问题并祝您编码愉快。
【讨论】:
感谢您的回答 (+1)【参考方案2】:当您将注释指定为构造函数参数时,您可以应用注释。此外,您可能需要使用元注释来限制您正在使用的注释应用于哪个目标 - 请参阅http://www.scala-lang.org/api/2.10.2-RC2/index.html#scala.annotation.meta.package
不过,您关于“依赖默认值”的问题有些不清楚。使用下划线初始化对应于将变量的值分配给 null。您还想到了哪些其他默认设置?
【讨论】:
我知道下划线符号用于分配默认值。但是,我想知道为什么 Scala 在类主体中声明时不允许使用 var name:String (没有下划线赋值)之类的东西。您指出了我不知道的 Scala (+1) 的一个不错的功能。但是,它不能满足我的需求,因为我还需要一个无参数构造函数,如果我在类定义中声明的构造函数中声明实例变量,则该构造函数会被覆盖 之所以需要赋值,我相信是为了让编译器能够区分抽象var(编译成一对抽象方法)和具体var,这也需要类文件中生成的字段。【参考方案3】:Scala 对类主体中的“var name: String”没有问题。你试过了吗?不过,这并不意味着你想要它的意思。这是一个抽象变量。
abstract class A
var name: String
// some possible uses for abstract vars
trait B type T ; var name: T
class B1 extends B type T = Int ; var name: Int = 5
// hey, no storage
class B2 extends B type T = String ; def name = "abc" ; def name_=(x: String) = ()
【讨论】:
如果我只是声明 var name:String;当编译成 .class 文件时,Scala 编译器会报错:未定义变量名。所以我想知道,即使是因为设计问题,为什么 Scala 不允许在类主体中使用 var name:String 而不声明其初始值;无论是默认值还是其他值 你可以重新阅读我的答案,你似乎忽略了。您是在问为什么存在“抽象”吗?未实现的抽象成员意味着您无法实例化该类。这是设计使然,就像在 java 中一样。以上是关于为啥 Scala 语言要求您初始化实例变量而不是依赖默认值?的主要内容,如果未能解决你的问题,请参考以下文章
在C语言中,为啥定义变量的时候总是初始化为0呢?该怎么理解。