1) Java時面向對象的編程語言,因爲歷史緣由,Java中海存在着非面向對象的內容:基本類型,null,靜態方法等java
2) Scala語言來自於Java,因此天生就是面向對象的語言,並且Scala時純粹的面相對象的語言,即在Scala中,一切皆爲對象程序員
3) 在面向對象的學習過程當中能夠對比着Java語言學習面試
1) 類是抽象的,概念的表明一類事物,好比人類,貓類...編程
2) 對象是具體的,實際的,表明一個具體事物框架
3) 類是對象的模版,對象是類的一個個體,對應一個實例編程語言
4) Scala中類和對象的區別和聯繫和Java是同樣的ide
-基本語法函數式編程
[修飾符] class 類名 {函數
類體工具
}
-定義類的注意事項
1) Scala語法中,類並不聲明爲public,全部這些類都具備公有可見性(默認就是public)
2) 一個Scala源文件能夠包含多個類,並且默認都是public
-基本介紹
屬性是類的一個組成部分,通常是值數據類型,也但是引用類型
-案例演示
class Dog { var name = "Tom" var lover = new Fish } class Fish { }
-注意事項和細節說明
1) 屬性的定義語法同變量,示例:[訪問修飾符] var 屬性名稱 [: 類型] = 屬性值
2) 屬性的定義類型能夠爲任意類型,包含值類型或引用類型
3) Scala中聲明一個屬性,必須顯示的初始化,而後根據初始化數據的類型自動推斷,屬性類型能夠省略(這點和Java不一樣)
4) 若是賦值爲null,則必定要加類型,由於不加類型,那麼該屬性的類型就是Null類型
5) 若是在定義屬性時,暫時不賦值,也可使用符號_(下劃線),讓系統分配默認值
class A { var a1: String = _ //null var a2: Byte = _ // 0 var a3: Double = _ // 0.0 var a4: Boolean = _ // false }
說明:屬性的高級部分和構造器(構造方法/函數)相關,具體介紹將在構造器部分詳解
-基本語法
val | var 對象名 [: 類型] = new 類型()
-說明
1) 若是咱們不但願改變對象的引用(即:內存地址),應該聲明爲val性質的,不然聲明爲var,Scala設計者推薦使用val,由於通常來講,在程序中,咱們只是改變對象屬性的值,而不是改變對象的引用
2) Scala在聲明對象變量時,能夠根據建立對象的類型自動推斷,因此類型聲明能夠省略,但當類型和後面new對象類型有繼承關係時即多態,就必須寫了
3) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val emp = new Emp // emp 類型就是Emp //若是咱們但願將子類對象,交給父類的引用,這時就須要寫上類型 val emp2: Person = new Emp } } class Person { } class Emp extends Person { }
-案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val p1 = new Person2 p1.name = "jack" p1.age = 10 val p2 = p1 println(p1 == p2) // true p1.name = "tom" println("p2.name=" + p2.name) // p2.name=tom } } class Person2 { var name = "" var age: Int = _ //若是是用 _ 方式給默認值,則屬性必須指定類型 }
-案例演示對應的內存佈局圖
Scala中的方法其實就是函數,聲明規則請參考函數式編程中的函數聲明
def 方法名[: 返回值類型] = {
方法體
}
給Cat類添加cal方法,能夠計算兩個數的和
object MethodDemo01 { def main(args: Array[String]): Unit = { val cat = new Cat println(cat.cal(10, 20)) } } class Cat { private var sal: Double = _ var food: String = _ //方法 def cal(n1: Int, n2: Int): Int = { return n1 + n2 } }
咱們來看一個需求:前面咱們在建立Person的對象時,是先把一個對象建立好後,再給他的姓名和年齡屬性賦值,若是如今要求,在建立Person類對象時,就直接制定這個對象的姓名和年齡,該怎麼作?這時就可使用構造方法/構造器
[修飾符] 方法名 (參數列表) {
構造方法體
}
1) 在Java中一個類能夠定義多個不一樣的構造方法,構造方法重載
2) 若是程序員沒有定義構造方法,系統會自動給類生成一個無參構造方法(也叫默認構造器),好比:Person(){}
3) 一旦定義了本身的構造方法(構造器),默認的構造方法就覆蓋了,就不能使用默認的無參構造方法,除非顯示的定義一下,即:Person(){}
在前面定義的Person類中添加兩個構造器
第一個無參構造器:利用構造器設置全部人的age屬性初始值都爲18
第二個帶name和age兩個參數的構造器:使得每次建立Person對象的同時初始化對象的name屬性值和age屬性值
public class Person { public String name; public int age; public String getInfo() { return name + "\t" + age; } public Person() { age = 18; } public Person(String name, int age) { this.name = name; this.age = age; } }
和Java同樣,Scala構造對象也須要調用構造方法,而且能夠有任意多個構造方法(即Scala中構造器也支持重載),Scala類的構造器包括:主構造器和輔助構造器
class 類名(形參列表) { //主構造器
def this(形參列表){ //輔助構造器
}
def this(形參列表){ //輔助構造器能夠有多個...
}
}
輔助構造器的函數名this,能夠有多個,編譯器經過不一樣參數來區分
建立Person對象的同時初始化對象的name屬性和age屬性,案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { // val p1 = new Person("Jack", 20) // println(p1) //下面這句話就會調用def this(name:String) val p2 = new Person("Tom") println(p2) } } //構造器的快速入門 //建立Person對象的同時初始化對象的age屬性值和name屬性值 class Person(inName: String, inAge: Int) { var name: String = inName var age: Int = inAge age += 10 println("~~~~~~~~~~") //重寫了toString,便於輸出對象的信息 override def toString: String = { "name=" + this.name + "\t age" + this.age } println("ok~~~~~") println("age=" + age) def this(name: String) { //輔助構造器,必須在第一行顯式調用主構造器(能夠是直接,也能夠是間接) this("Jack", 10) //this this.name = name //從新賦值 } }
1) Scala構造器的做用是完成對新對象的初始化,構造器沒有返回值
2) 主構造器的聲明直接放置於類名以後
3) 主構造器會執行類定義中的全部語句,這裏能夠體會到Scala的函數式編程和麪向對象編程融合在一塊兒,即:構造器也是方法(函數),傳遞參數和使用方法和前面的函數部份內容沒有區別
4) 若是主構造器沒有參數,小括號能夠省略,構建對象時調用的構造方法的小括號也能夠省略
class AA { } val a = new AA val b = new AA()
5) 輔助構造器名稱爲this(這個和Java是不同的),多個輔助構造器經過不一樣參數列表進行區分,在底層就是構造器重載
object boke_demo01 { def main(args: Array[String]): Unit = { val p1 = new Person2("jack") p1.showInfo() } } //定義了一個Person類 //Person 有幾個構造器 4 class Person2 private() { var name: String = _ var age: Int = _ def this(name: String) { //輔助構造器不管是直接或間接,最終都必定要調用主構造器,執行主構造器的邏輯 //並且須要放在輔助構造器的第一行[這點和java同樣,java中一個構造器要調用同類的其它構造器,也須要放在第一行] this() //直接調用主構造器 this.name = name } //輔助構造器 def this(name: String, age: Int) { this() //直接調用主構造器 this.name = name this.age = age } def this(age: Int) { this("匿名") //調用主構造器,由於 def this(name : String) 中調用了主構造器! this.age = age } def showInfo(): Unit = { println("person信息以下:") println("name=" + this.name) println("age=" + this.age) } }
6) 若是想要主構造器編程私有的,能夠在()以前加上private,這樣用戶只能經過輔助構造器來構造對象了,好比: class Person2 private(){}
7) 輔助構造器的聲明不能和主構造器的聲明一致,會發生錯誤(即構造器名重複)
對屬性的內容作一個增強
1) Scala類的主構造器的形參未用任何修飾符修飾,那麼這個參數是局部變量
2) 若是參數使用val關鍵字聲明,那麼Scala會將參數做爲類的私有隻讀屬性使用
3) 若是參數使用var關鍵字聲明,那麼Scala會將參數做爲類的成員屬性使用,並會提供對應的xxx()[相似getter]/xxx_$eq()[相似setter]方法,即這時的成員屬性是私有的,可是可讀寫
4) 案例演示
object boke_demo01 { def main(args: Array[String]): Unit = { val worker = new Worker("smith") worker.name //不能訪問 inName val worker2 = new Worker2("smith2") worker2.inName //能夠訪問 inName println("hello!") val worker3 = new Worker3("jack") worker3.inName = "mary" println(worker3.inName) } } //若是 主構造器是Worker(inName: String) ,那麼 inName就是一個局部變量 class Worker(inName: String) { var name = inName } //若是 主構造器是Worker2(val inName: String) ,那麼 inName就是Worker2的一個private的只讀屬性 class Worker2(val inName: String) { var name = inName } // 若是 主構造器是Worker3(var inName: String) ,那麼 inName就是Worker3的一個 // 一個private 的能夠讀寫屬性 class Worker3(var inName: String) { var name = inName }
JavaBean規範定義了Java的屬性是像getXxx()和setXxx()方法。許多Java工具(框架)都依賴這個命名習慣。爲了Java的互操做性。將Scala字段加@BeanProperty時,這樣會自動生成規範的setXxx/getXxx方法。這時可使用 對象.setXxx()和 對象.getXxx()來調用屬性
注意:給某個屬性加入@BeanPropetry註解後,會生成getXxx和setXxx的方法,而且對原來底層自動生成相似xxx(),xxx_$eq()方法,沒有衝突,兩者能夠共存
import scala.beans.BeanProperty object boke_demo01 { def main(args: Array[String]): Unit = { val car = new Car car.name = "寶馬" println(car.name) //使用 @BeanProperty 自動生成 getXxx 和 setXxx car.setName("奔馳") println(car.getName()) } } class Car { @BeanProperty var name: String = null }
class Person { var age: Short = 90 var name: String = _ def this(n: String, a: Int) { this() this.name = n this.age = a } } var p: Person = new Person ("小倩", 20)
1) 加載類的信息(屬性信息,方法信息)
2) 在內存中(堆)開闢空間
3) 使用父類的構造器(主和輔助)進行初始化
4) 使用主構造器對屬性進行初始化[age:90, name:null]
5) 使用輔助構造器對屬性進行初始化[age:20, name:小倩]
6) 將開闢的對象的地址賦給p這個引用