我仍然在試圖總結我的頭周圍斯卡拉構造如何將以下Java構造函數代碼轉換爲Scala?
public class MyClass {
private String myString = null;
public MyClass() {
myString = "hello";
}
}
我仍然在試圖總結我的頭周圍斯卡拉構造如何將以下Java構造函數代碼轉換爲Scala?
public class MyClass {
private String myString = null;
public MyClass() {
myString = "hello";
}
}
在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
的整件事情完全是浪費;你加載它,然後立即覆蓋它。
現在,如果我們看一下相應的斯卡拉:
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
是一種提醒自己,在使用之前最好先初始化它的方法。
但斯卡拉不會讓你這樣做。斯卡拉真的只允許一個構造函數;其他人只是調用這個構造函數的別名。如果需要,您可以將其設置爲私有並使用大量參數進行加載,但重點是具有多個構造函數,其中一些設置了關鍵數據,而其中一些卻不是實際上是一個容易出錯的過程。最好只做一次,並寫下如
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
,然後你就會有一些看起來更像地道斯卡拉。
你的構造函數是默認的,它不接受任何參數。這相當於不定義構造函數並將屬性myString設置爲「hello」。既然你將它定義爲一個val,它將是不可變的(不可等同於一個java setter可用),但是你可以通過。訪問myString的值。符號(例如myClass.myString
)
class MyClass {
val myString = "hello"
}