如何将以下Java构造函数代码转换为Scala?

时间:2011-07-16 02:09:40

标签: scala

我仍然试图绕过Scala构造函数

public class MyClass {
    private String myString = null;

    public MyClass() {
        myString = "hello";
    }
} 

2 个答案:

答案 0 :(得分:9)

在Scala中你只会做

class MyClass {
  private var myString = "hello"
}

这看起来不一样,是吗?但是让我们看一下Java代码实际生成的字节码(让我们称之为JavaConstructor类):

public JavaConstructor();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aconst_null
   6:   putfield    #2; //Field myString:Ljava/lang/String;
   9:   aload_0
   10:  ldc #3; //String hello
   12:  putfield    #2; //Field myString:Ljava/lang/String;
   15:  return

Java已经有效地将private String myString = null;复制到构造函数中(注意创建和存储null的第5行和第6行)。因此,将myString设置为null的全部内容完全是浪费精力;你加载它然后立即覆盖它。

现在,如果我们查看相应的Scala:

public ScalaConstructor();
  Code:
   0:   aload_0
   1:   invokespecial   #18; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   ldc #20; //String hello
   7:   putfield    #10; //Field myString:Ljava/lang/String;
   10:  return
}

我们认为它与人们希望的一样有效(并反映了代码)。

然后问题是:为什么你想要像在Java中那样做?好吧,也许你有多个构造函数,其中一些将设置myString,有些则不会!将其设置为null是一种提醒自己在使用之前最好初始化它的方法。

但斯卡拉不会让你这样做。 Scala实际上只允许一个构造函数;其他只是称为一个构造函数的别名。如果需要,您可以将其设置为私有并使用大量参数加载它,但重点是具有多个构造函数,其中一些构造关键数据,而其中一些构造函数实际上不是一个容易出错的过程。最好只做一次,并编写类似

的内容
private var myString = if (someParameter) "hello" else null

如果你真的需要这样做。然后,也许你只把它变成var,因为你试图在不同的构造函数中设置它。只有一个构造函数,也许没有必要:

private val myString = if (someParameter) "hello" else null

但也许现在它设置正确,我们并不需要它是私密的。

val myString = if (someParameter) "hello" else null

并且如果经常没有设置,我们应该使用一个选项:

val myString = if (someParameter) Some("hello") else None

然后你会看到更像是惯用的Scala。

答案 1 :(得分:1)

您的构造函数是默认构造函数,它不接受任何参数。它等同于定义没有构造函数并将属性myString设置为“hello”。由于您将其定义为val,因此它将是不可变的(不等同于java setter可用),但您可以通过以下方式访问myString的值。符号(例如myClass.myString

class MyClass {
  val myString = "hello"
}