我仍然试图绕过Scala构造函数
public class MyClass {
private String myString = null;
public MyClass() {
myString = "hello";
}
}
答案 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"
}