探索Scala(2)-- Traits
本文記錄我對Scala語言Traits的一些理解。
trait >= interface
Scala語言沒有介面(Interface)的概念,取而代之的,是功能更加強大的Trait。因此,interface在Scala語言裡並不是關鍵字,我們可以自由的使用它,如下面這段程式碼所示:
但是要注意,上面的程式碼雖然是合法的Scala程式碼,能編譯出ScalaObject.class。但是如果想在Java里正常使用這個class的話,就會遇到問題。
沒有具體方法的Trait會被編譯成介面
如果一個Trait沒有定義任何有具體實現的方法,那麼它和介面是等價的。換句話說,如果一個Trait的所有方法(如果有的話)全都是抽象的,那麼Scala會把它編譯成Java介面。比如下面這個沒有任何方法的TraitA:
會被編譯成TraitA.class,分析class檔案可以知道,它其實等價於下面的Marker介面:
public interface TraitA {
}
再比如下面這個有兩個抽象方法的TraitB:
會被編譯為:
public interface TraitB {
public int m1();
public int m2(int arg);
}
有具體方法的Trait會被編譯成兩個class檔案
以下面這個TraitC為例:
編譯之後得到兩個class檔案:TraitC.class和TraitC$class.class。分析class檔案可以知道,TraitC.class實際上是一個介面,如下所示:
public interface TraitC {
public int m3(int arg);
}
方法實現在TraitC$class.class裡,如下所示:
public abstract class TraitC$class {
public static int m3(TraitC t, int arg) {
return 1;
}
public static void $init$() {
//return;
}
}
由此可知:
- Trait會被編譯為等價的介面
- 如果Trait有具體方法,則這些方法會被複制到相應的$class類裡,並且有下面兩處變動:
- 方法變為static
- Trait例項被插入到引數列表的最開始
欄位(Fields)
如果Trait定義了欄位呢?比如下面這個TraitD:
編譯之後,仍然會得到兩個class檔案,如下所示:
public interface TraitD {
public int f1();
public void f1_$eq(int i);
}
public abstract class TraitD$class {
public static void $init$(TraitD t) {
t.f1_$eq(1);
}
}
由此可知:
- Trait仍然被編譯成了等價的介面,但var欄位被替換成了一對兒getter/setter方法。需要注意的是,這對getter/setter方法並沒有按照JavaBean風格來命名
- 相應的$class類裡只有一個$init$方法
Mix in Traits
下面通過一個類來觀察一下mix in上面提到的Traits之後,會發生什麼:
下面是反編譯之後的MyClass(Java)程式碼:
public class MixedIn implements TraitA, TraitB, TraitC, TraitD {
private int f1;
public MixedIn() {
TraitC$class.$init$(this);
TraitD$class.$init$(this);
}
public int f1() {
return this.f1;
}
public void f1_$eq(int val) {
this.f1 = val;
}
public int m1() {
return 0;
}
public int m2(int arg) {
return arg;
}
public int m3(int arg) {
return TraitC$class.m3(this, arg);
}
}
分析如下:
- TraitA沒有定義任何方法,所以只是繼承了介面
- TraitB有兩個抽象方法(m1、m2),所以我們必須自己實現這兩個方法
- TraitC有一個具體方法(m3),被Scala編譯器實現
- TraitD定義了一個欄位,也被編譯器實現
- 編譯器還生成了一個建構函式,呼叫了TraitC和TraitD的$init$方法
相關文章
- 從 Java 到 Scala(四):TraitsJavaAI
- C++ 萃取機 Iterator TraitsC++AI
- PHP 物件導向 (十)TraitsPHP物件AI
- [2]SpinalHDL教程——Scala簡單入門
- Scala學習筆記(2)-基礎語法筆記
- PHP模擬多繼承的方式:traitsPHP繼承AI
- Scala
- 實驗 2 Scala 程式設計初級實踐程式設計
- Rust中的併發性:Sync 和 Send TraitsRustAI
- Scala 簡介 [摘自 Scala程式設計 ]程式設計
- Scala學習總結(from scala for the Impatient)
- 2-2 Scala專案構建工具sbt和IntelliJ IDEA環境配置IntelliJIdea
- Awesome Scala
- scala(一)
- Scala - DataFrame
- scala入門之編寫scala指令碼指令碼
- 深圳scala-meetup-20180902(2)- Future vs Task and ReaderMonad依賴注入依賴注入
- Scala(四):物件物件
- Scala(三):類
- scala(四)集合
- Scala操作Map
- Scala特質
- scala 列舉
- STL-空間配置器、迭代器、traits程式設計技巧AI程式設計
- 【翻譯】Traits:一種新的而且有用的Template技巧AI
- Flink - 安裝包scala 2.12和scala 2.11的區別
- The Coding Kata: FizzBuzzWhizz in Scala
- Scala筆記(一)筆記
- scala(二)-for迴圈
- scala(三)函式函式
- Scala 類和物件物件
- Scala 語法(一)
- Scala陣列操作陣列
- scala中的sealed
- scala怎麼退出
- Scala 的學習
- scala物件導向物件
- 17 scala集合使用
- Intellij IDEA 安裝Scala外掛 + 建立Scala專案(Hello World!)IntelliJIdea