簡體   English   中英

為什么Scala在已經具有特征的情況下會有課程?

[英]Why does Scala have classes when it already has traits?

這似乎是一個愚蠢的問題,所以請耐心等待......

考慮一下這個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 = $anon$1@78db81f3

scala> class C
defined class C

scala> val c = new C
c: C = C@170a6001

我們可以像使用類一樣使用特征,除了我們必須在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 = $anon$1@6a688d6f

scala> t2.s
res0: java.lang.String = test

scala> class C2 { val s = "test" }
defined class C2

scala> val c2 = new C2
c2: C2 = C2@73ea7821

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 = $anon$1@1f2f0ce9

scala> abstract class C3 { val s: String }
defined class C3

scala> val c3 = new C3 { val s = "test" }
c3: C3 = $anon$1@207a8313

如果您忘記必須定義一些成員,則兩種方式都會給您編譯錯誤:

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 = $anon$1@479e0994

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

所以我再次問,為什么當特征顯然更簡單,更強大時,Scala會對課程感到困擾?

我假設原因是與Java的概念和實際兼容性,但我想知道是否可以在幕后維護代碼兼容性。 據我所知,Scala特性只是在幕后成為Java類,為什么不能反過來發生Scala認為Java類本質上是特征?

與此相關,為什么不允許在不必要時刪除大括號? 例如:

val t = new T

此時, 作為用戶 ,特征與當前的Scala類無法區分,但當然更好。

特征和類之間有幾個不同之處:

  • 特征不能采用構造函數參數。 這個限制可能會在某個時候解除,但這是一個難題。 特征可以在層次結構中多次繼承,並且每個實例化可以為構造函數參數提供不同的值

  • 特征被編譯為Java接口和實現類(攜帶具體方法)。 這意味着它有點慢,因為所有調用都通過接口,如果它們是具體的,它們將被轉發到它們的實現

  • 具體成員的特征不能在Java中很好地繼承(它可以,但它看起來像一個接口,因此具體成員仍然需要用Java實現)。

我不認為類和特征之間的區別會消失,主要是因為最后兩項。 但如果第一點得到解決,它們可能會變得更容易使用。 關於沒有{}實例化,這是一個可以添加的便利,但我個人不喜歡它:每個實例化創建一個新 (一個匿名的),並且應該向程序員表明情況就是這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM