標籤:

Scala的Class、Object、Trait

Scala的Class、Object、Trait

來自專欄 數據科學家的自我修養

開發環境

ideaIU或ideaIC。

idea的scala插件,File-Setting-Plugins,搜索scala在線安裝,或下載後離線安裝Install plugin from disk。

載入scala的包,Project Structure,Global Libraries,添加scala-sdk。

基礎

scala中,break和continue的實現

package com.padluo.spark.scala.basicimport scala.util.control.Breaks._object BreakTest { def main(args: Array[String]): Unit = { // break breakable { for (i <- 1 to 10) { if (i == 2) { break() } println(i) } } // continue for (i <- 1 to 10) { breakable { if (i == 2) { break() } println(i) } } }}

0 until 100 to 10的區別,until是0到9,相當於<,to是0到10,相當於<=。

scala用Java裡面的類庫

package com.padluo.spark.scala.basicimport java.text.SimpleDateFormatimport java.util.{Calendar, Date}object UseJava { def main(args: Array[String]): Unit = { val sdf:SimpleDateFormat = new SimpleDateFormat("yy-MM-dd") val c = Calendar.getInstance() println(c.getTime) println(sdf.format(c.getTime)) // Convert Code from Java,可以直接把Java代碼貼到scala文件中來 val sdf2: SimpleDateFormat = new SimpleDateFormat("yy-MM-dd") sdf2.format(new Date) }}

Class、Object、Trait

類class里無static類型,類里的屬性和方法,必須通過new出來的對象來調用,所以有main主函數也沒用。

而object的特點是:

  • 可以擁有屬性和方法,且默認都是"static"類型,可以直接用object名直接調用屬性和方法,不需要通過new出來的對象(也不支持)。
  • object里的main函數式應用程序的入口。
  • object和class有很多和class相同的地方,可以extends父類或Trait,但object不可以extends object,即object無法作為父類。

構造函數

  • 一個主構造器(函數),其他是輔助構造器
  • 輔助構造器的實現體里,必須引用(調用)主構造器
  • 主構造器的參數,也會成為類的屬性(?正確嗎?)
  • 輔助構造函數的名稱都是this
  • 輔助構造函數中必須以一個其他輔助構造器或主構造器的調用開始

Bean屬性,定義getter和settet方法。

// TestVo.scalapackage com.padluo.spark.scala.basicimport scala.beans.BeanPropertyclass TestVo { // class 里的屬性默認是private類型,object里的屬性默認是static @BeanProperty var id = 10 @BeanProperty var name = null @BeanProperty var addr = null}// TestVoMain.scalapackage com.padluo.spark.scala.basicobject TestVoMain { def main(args: Array[String]): Unit = { var vo = new TestVo println(vo.getId) }}

伴生對象

如何實現同個類既有普通方法又有靜態方法?

伴生類和伴生對象可以相互訪問彼此的私有成員。

package com.padluo.spark.scala.basicclass BanSheng { def add2(a: Int, b: Int): Int = { a + b }}object BanSheng { def add(a: Int, b: Int): Int = { a + b } def main(args: Array[String]): Unit = { BanSheng.add(1, 2) // 靜態函數 val banSheng = new BanSheng banSheng.add2(3, 4) }}

javap BanSheng.class反編譯後,

public class com.padluo.spark.scala.basic.BanSheng { public static void main(java.lang.String[]); public static int add(int, int); public int add2(int, int); public com.padluo.spark.scala.basic.BanSheng();}

伴生對象的apply方法

package com.padluo.spark.scala.basicclass BanSheng(id: Int) { def add2(a: Int, b: Int): Int = { a + b }}object BanSheng { def apply(id: Int): BanSheng = { println("----apply-----") new BanSheng(id) } def add(a: Int, b: Int): Int = { a + b } def main(args: Array[String]): Unit = { BanSheng.add(1, 2) // 靜態函數 val banSheng = new BanSheng(1) banSheng.add2(3, 4) val c = BanSheng(200) val cc = BanSheng.apply(200) }}

單例模式

package com.padluo.spark.scala.basicclass SingleTon {}object SingleTon { private var s:SingleTon = null def getInstance():SingleTon = { if(s == null) { new SingleTon() } else { s } } def main(args: Array[String]): Unit = { val singleTon = SingleTon.getInstance() println(singleTon) }}

繼承

  • 繼承關鍵詞extends,多個用with。
  • 某類如果不想被繼承,可定義為final類型
  • 用super調用父類的方法或屬性
  • 重寫方法時必須用override,可以重寫欄位,不想被重寫則定義為final類型
  • 只有主構造器可以調父類的主構造器

Father.scala

package com.padluo.spark.scala.basicclass Father(name: String, age: Int) { def doEat(food: String) { println("eatting .." + food) } def printInfo2() { println("name:" + name + ",age:" + age) }}

Son.scala

package com.padluo.spark.scala.basicclass Son(name: String, age: Int, addr: String) extends Father(name, age) { // 子類把name和age傳入到父類中 override def doEat(food: String) { println("my eatting .." + food) } def printInfo() { super.printInfo2() println("name:" + name + ",age:" + age + ",addr:" + addr) }}object Son { def main(args: Array[String]): Unit = { val s: Son = new Son("zhangsan", 30, "beijing") s.printInfo() }}

Scala類層級結構

Scala里,每個類都繼承自通用的名為Any的超類。因為所有的類都是Any的子類,所以定義在Any中的方法就是「共同的」方法:它們可以被任何對象調用。

因為每個類都繼承自Any,所以Scala程序里的每個對象都能用==、!=或equals比較,用hashCode做散列,以及用toString轉為字元串。Any類里的等號和不等號方法被聲明為final,因此他們不能再子類里重寫。實際上,==總是與equals相同,!=總是與equeal相反。因此,獨立的類可以通過重寫equals方法改變==!=的意義。

Any有兩個子類:AnyVal和AnyRef(相當於Java里的Object)。

AnyVal是Scala里每個內建值類的父類。有9個這樣的值類:Byte、Short、Char、Int、Long、Float、Double、Boolean和Unit。其中的前8個都對應到Java的基本類型。這些值類都被定義為既是抽象的又是final的,不能使用new創造這些類的實例。Unit被用作不返回任何結果的方法的結果類型。Unit只有一個實例值,寫成()。

AnyRef類是Scala里所有引用類(reference class)的基類。它其實是Java平台上java.lang.Object類的別名。因此Java里寫的類和Scala里寫的都繼承自AnyRef。

Scala類與Java類的不同在於它們還繼承自一個名為ScalaObject的特別trait。是想要通過ScalaObject包含的Scala編譯器定義和實現的方法讓Scala程序的執行更高效。

scala.Null和scala.Nothing是用統一的方式處理Scala面向對象類型系統的某些「邊界情況」的特殊類型。Null類是null引用對象的類型,它是每個引用類(繼承自AnyRef的類)的子類。Null不兼容值類型。Nothing類型在Scala的類層級的最低端;它是任何其他類型的子類型。然而,根本沒有這個類型的任何值。Nothing的一個用處是它標明了不正常的終止。

Trait特質

為什麼不可以繼承多個父類?原因是多個父類里有相同函數或屬性時,無法控制用哪個。

Scala的Trait相當於Java里的Interface,但Trait不僅可以定義函數,還可以有函數體實現。實現關鍵詞是extends,實現多個Trait用with。當extends的多個Trait里有相同函數時,子類必須重寫該函數。

  • 父trait里無函數體的函數,子類必須override
  • 重寫父類里有函數體的函數,必須有關鍵詞override
  • trait里的變數,都是val類型
  • 在trait里定義的的變數,必須是val類型,如果變數沒初始化,子類必須override

案例1,

trait TestTrait { def fun()}

反編譯後為

public interface com.padluo.spark.scala.basic.TestTrait { public abstract void fun();}

當def fun()改為def fun(){} 時,反編譯結果如何?

trait TestTrait { def fun() {}}

反編譯後為(有問題???)

D:JavaideaIdeaProjectsspark-studyspark-core argetclassescompadluosparkscalaasic>javap TestTrait.classCompiled from "TestTrait.scala"public abstract class com.padluo.spark.scala.basic.TestTrait$class { public static void fun(com.padluo.spark.scala.basic.TestTrait); public static void $init$(com.padluo.spark.scala.basic.TestTrait);}D:JavaideaIdeaProjectsspark-studyspark-core argetclassescompadluosparkscalaasic>javap TestTrait$class.classCompiled from "TestTrait.scala"public abstract class com.padluo.spark.scala.basic.TestTrait$class { public static void fun(com.padluo.spark.scala.basic.TestTrait); public static void $init$(com.padluo.spark.scala.basic.TestTrait);}

案例2,

trait TestTrait { def fun() { println("---") } def fun200()}

反編譯後為(有問題)

D:JavaideaIdeaProjectsspark-studyspark-core argetclassescompadluosparkscalaasic>javap TestTrait.classCompiled from "TestTrait.scala"public abstract class com.padluo.spark.scala.basic.TestTrait$class { public static void fun(com.padluo.spark.scala.basic.TestTrait); public static void $init$(com.padluo.spark.scala.basic.TestTrait);}D:JavaideaIdeaProjectsspark-studyspark-core argetclassescompadluosparkscalaasic>javap TestTrait$class.classCompiled from "TestTrait.scala"public abstract class com.padluo.spark.scala.basic.TestTrait$class { public static void fun(com.padluo.spark.scala.basic.TestTrait); public static void $init$(com.padluo.spark.scala.basic.TestTrait);


本文首發於steem,感謝閱讀,轉載請註明。

steemit.com/@padluo


微信公眾號「padluo」,分享數據科學家的自我修養,既然遇見,不如一起成長。

weixin.qq.com/r/P3WGnj3 (二維碼自動識別)


讀者交流電報群

t.me/sspadluo


知識星球交流群

推薦閱讀:

Spark源碼分析(3) RDD 的轉換
spark在那裡指定master URL呢?
Spark Streaming:大規模流式數據處理的新貴
Spark里的DAG是怎麼回事?
從頭學習大數據培訓課程 spark 基於內存的分散式計算框架(二)RDD 編程基礎使用

TAG:Spark | Scala |