为啥 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 语言要求您初始化实例变量而不是依赖默认值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥方法局部静态变量绑定到类而不是实例?

为啥kafka 用scala

在C语言中,为啥定义变量的时候总是初始化为0呢?该怎么理解。

大哥我是昨天问的c语言问题,问一下,给变量赋初值为啥啊?能全赋0吗

C语言指针变量为啥要赋初值?

scala设计者为啥要提供package object