這似乎是一個愚蠢的問題,所以我承擔......爲什麼Scala在已經有特徵的時候就已經上課了?
考慮這個REPL會話:
scala> trait T
defined trait T
scala> val t = new T
<console>:8: error: trait T is abstract; cannot be instantiated
val t = new T
^
scala> val t = new T {}
t: java.lang.Object with T = [email protected]
scala> class C
defined class C
scala> val c = new C
c: C = [email protected]
我們可以用一個特質,就像一類,但我們必須添加{}
之後的new T
。事實上,我們基本上混合了T
到java.lang.Object
,這實際上對我很有意義。
如果我們的成員,再次只有{}
必須添加:
scala> trait T2 { val s = "test" }
defined trait T2
scala> val t2 = new T2
<console>:8: error: trait T2 is abstract; cannot be instantiated
val t2 = new T2
^
scala> val t2 = new T2 {}
t2: java.lang.Object with T2 = [email protected]
scala> t2.s
res0: java.lang.String = test
scala> class C2 { val s = "test" }
defined class C2
scala> val c2 = new C2
c2: C2 = [email protected]
scala> c2.s
res1: java.lang.String = test
如果我們有抽象成員則性狀聲明是由幾個字符實際上更短,更重要的是,在我的眼中更加一致(不需要記得把abstract
在聲明前):
scala> trait T3 { val s: String }
defined trait T3
scala> val t3 = new T3 { val s = "test" }
t3: java.lang.Object with T3 = [email protected]
scala> abstract class C3 { val s: String }
defined class C3
scala> val c3 = new C3 { val s = "test" }
c3: C3 = [email protected]
如果你忘了,你必須定義一些成員,左右逢源給你編譯錯誤:
scala> val badt3 = new T3 {}
<console>:7: error: object creation impossible, since value s in trait T3 of type String is not defined
val badt3 = new T3 {}
scala> class BadC3 { val s: String }
<console>:8: error: class BadC3 needs to be abstract, since value s is not defined
class BadC3 { val s: String }
如果我們試圖做更復雜的事情,然後性狀的力量自然變得更加明顯:
scala> val t4 = new T with T2
t4: java.lang.Object with T with T2 = [email protected]
scala> val c4 = new C with C2
<console>:9: error: class C2 needs to be a trait to be mixed in
val c4 = new C with C2
所以我再次問,爲什麼斯卡拉帶班懶得在所有的時候特質顯然是既更簡單,更強大?
我假設原因是Java的概念性和實際兼容性,但我想知道代碼兼容性是否可以在幕後維護。據我瞭解,斯卡拉特質只是在幕後成爲Java類,所以爲什麼不能發生逆轉,Scala認爲Java類實質上是特質?
與此相關的是,爲什麼不允許在不必要時丟棄大括號?例如:
val t = new T
在這一點上,作爲用戶,性狀是由目前的Scala類沒有區別,但當然更好。
你寫的每一次'新款T {}'你創建一個新的匿名類。不是那種你想要的開銷。此外,'T'的幾個「實例」將不會具有相同的類型。 – Raphael