首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala主构造函数及其生成的字段/属性

Scala主构造函数及其生成的字段/属性
EN

Stack Overflow用户
提问于 2017-03-18 17:29:55
回答 2查看 850关注 0票数 2

对于Scala来说,无论我读了多少篇文章/教程(比如这些 \\ / 几个),我似乎都不知道构造函数是如何工作的。

让我们举三个主构造函数的例子如下:

代码语言:javascript
复制
// 1
class Fizz(buzz : Buzz) { ... }

// 2
class Fizz (val buzz : Buzz) { ... }

// 3
class Fizz (var buzz : Buzz) { ... }

其中每一项:

  • 是否创建了buzz属性?
    • 若然,是否公开?
    • 是可变的吗?
    • 是静态的吗?
    • 是为它而创建的getter/setter吗?

  • 创建了buzz字段吗?
    • 若然,是否公开?
    • 是可变的吗?
    • 是静态的吗?
    • 是为它而创建的getter/setter吗?

  • 还有什么特别的/值得注意的吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-18 18:47:57

在Scala中,构造函数实际上是一种很棒的野兽。实际上,Scala编译器能够为您做出一些明智的选择。

根据您问题的措辞,我认为您可能有一些Java方面的经验。为了非常清楚地说明正在发生的事情--并允许您在未来进行试验--让我们对Scala编译器生成的代码进行反编译,这样我们就可以看到Java的等价物。为了简洁起见,我只展示方法/字段的声明,而不是它们的实现。

没有限定符,buzz只在构造函数中使用

代码语言:javascript
复制
class Fizz(buzz : Buzz)

将编译成相当于

代码语言:javascript
复制
public class Fizz {
    public Fizz(Buzz);
}

由于Fizz不声明引用buzz的任何方法/字段(除了构造函数本身),Scala将不会为其创建任何字段/方法。

没有限定符,在构造函数之外引用buzz

代码语言:javascript
复制
class Fizz(buzz : Buzz) {
    def foo: Buzz = buzz
}

这一次,buzzfoo方法使用,因此编译器必须将其存储为字段。由于该字段未被声明为var,因此将成为private final

代码语言:javascript
复制
public class Fizz {
  private final Buzz buzz;
  public Buzz foo();
  public Fizz(Buzz);
}

val限定符

代码语言:javascript
复制
class Fizz(val buzz : Buzz)

这一次,您明确表示希望buzz成为val。这将产生创建一个private final字段以容纳buzz的效果,以及一个相同的公共方法来访问它。

代码语言:javascript
复制
public class Fizz {
  private final Buzz buzz;
  public Buzz buzz();
  public Fizz(Buzz);
}

var限定符

代码语言:javascript
复制
class Fizz(var buzz : Buzz)

这个例子与前一个非常相似,只是现在您指定您希望能够修改buzz。这将导致Scala编译器以有趣的名称buzz_$eq为您提供一个setter方法。仅由于命名方法中的$约束,才需要使用JVM。在Scala代码中,此方法将显示为buzz_=,而语法糖将允许您将其称为fizz.buzz = someBuzz。这样,你看起来就像在变场一样,但实际上你只是在叫一个策划者。

代码语言:javascript
复制
public class Fizz {
  private Buzz buzz;
  public Buzz buzz();
  public void buzz_$eq(Buzz);
  public Fizz(Buzz);
}

如何分解Scala?

在研究这类问题时,这些命令很有帮助:

代码语言:javascript
复制
scalac Fizz.scala

将创建一个非人类可读的编译Fizz.class。您可以使用以下方法将其解压缩成Java版本

代码语言:javascript
复制
javap -constants -p Fizz

在包含Fizz.class的目录中

票数 5
EN

Stack Overflow用户

发布于 2017-03-18 17:42:43

在所有情况下,您显示的字段也是构造函数的参数。

声明为val或var的参数成为公共成员。如果在构造函数中使用变量,它们将不会成为成员,如果在类中使用它们,则它们将是私有成员。

在第一种情况下,class Fizz(buzz : Buzz){}参数是不可变的,不会成为成员(我假设您在任何地方都不使用它)。

在第二种情况下,class Fizz (val buzz : Buzz) {}buzz参数是不可变的,并成为公共成员。

在第三种情况下,class Fizz (var buzz : Buzz) {}buzz参数是可变的,并成为公共成员。

同样,在所有情况下,都没有自动创建的getter或setter。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42877572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档