object
object就谜,相當(dāng)于class的單個(gè)實(shí)例,通常在里面放一些靜態(tài)的field或者method
第一次調(diào)用object的方法時(shí)娩践,就會(huì)執(zhí)行object的constructor活翩,也就是object內(nèi)部不在method中的代碼逞带;但是object不能定義接受參數(shù)的constructor
注意,object的constructor只會(huì)在其第一次被調(diào)用時(shí)執(zhí)行一次纱新,以后再次調(diào)用就不會(huì)再次執(zhí)行constructor了
object通常用于作為單例模式的實(shí)現(xiàn),或者放class的靜態(tài)成員穆趴,比如工具方法
object People{
private var eyeNum:Int = 2
println("i'm a people")
def getEyeNumber = eyeNum
}
println(People.getEyeNumber)
println(People.getEyeNumber)
println(People.getEyeNumber)
伴生對(duì)象
如果有一個(gè)class脸爱,還有一個(gè)與class同名的object,那么就稱這個(gè)object是class的伴生對(duì)象未妹,class是object的伴生類
伴生類和伴生對(duì)象必須存放在一個(gè).scala文件之中
伴生類和伴生對(duì)象簿废,最大的特點(diǎn)就在于,互相可以訪問(wèn)private field
class People{
private var name = "ZhaoJun"
def getName = "Hello, my name is " + name + " ,i have " + People.eyeNum + " eyes."
}
object People{
private var eyeNum:Int = 2
println("i'm a people")
def getEyeNumber = eyeNum
}
var people = new People
println(people.getName)
讓object繼承抽象類
object的功能其實(shí)和class類似络它,除了不能定義接受參數(shù)的constructor之外
object也可以繼承抽象類族檬,并覆蓋抽象類中的方法
abstract class Hello(var name:String){
def sayHello
}
object HelloPeople extends Hello("hello"){
override def sayHello: Unit = println("message " + name)
}
HelloPeople.sayHello
apply方法
object中非常重要的一個(gè)特殊方法,就是apply方法
通常在伴生對(duì)象中實(shí)現(xiàn)apply方法化戳,并在其中實(shí)現(xiàn)構(gòu)造伴生類的對(duì)象的功能
而創(chuàng)建伴生類的對(duì)象時(shí)单料,通常不會(huì)使用new Class的方式,而是使用Class()的方式点楼,隱式地調(diào)用伴生對(duì)象得apply方法扫尖,這樣會(huì)讓對(duì)象創(chuàng)建更加簡(jiǎn)潔
比如,Array類的伴生對(duì)象的apply方法就實(shí)現(xiàn)了接收可變數(shù)量的參數(shù)掠廓,并創(chuàng)建一個(gè)Array對(duì)象的功能
def apply(x: Int, xs: Int*): Array[Int] = {
val array = new Array[Int](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
比如换怖,定義自己的伴生類和伴生對(duì)象
class People{
private var name = "ZhaoJun"
def getName = "Hello, my name is " + name + " ,i have " + People.eyeNum + " eyes."
}
object People{
private var eyeNum:Int = 2
println("i'm a people")
def getEyeNumber = eyeNum
def apply(): People = new People()
}
var people = People()
println(people.getName)
main方法
就如同java中,如果要運(yùn)行一個(gè)程序蟀瞧,必須編寫一個(gè)包含main方法類一樣沉颂;在scala中,如果要運(yùn)行一個(gè)應(yīng)用程序悦污,那么必須有一個(gè)main方法铸屉,作為入口
scala中的main方法定義為def main(args: Array[String]),而且必須定義在object中
object HelloMain {
def main(args: Array[String]): Unit = {
println("Hello Main")
}
}
除了自己實(shí)現(xiàn)main方法之外塞关,還可以繼承App Trait抬探,然后將需要在main方法中運(yùn)行的代碼,直接作為object的constructor代碼帆赢;而且用args可以接受傳入的參數(shù)
App Trait的工作原理為:App Trait繼承自DelayedInit Trait小压,scalac命令進(jìn)行編譯時(shí),會(huì)把繼承App Trait的object的constructor代碼都放到DelayedInit Trait的delayedInit方法中執(zhí)行
object HelloAppMain extends App {
println("Hello Main")
}
如果要運(yùn)行上述代碼椰于,需要將其放入.scala文件怠益,然后先使用scalac編譯,再用scala執(zhí)行
scalac HelloAppMain.scala
scala HelloAppMain
或者
scalac HelloApp.scala
scala HelloApp
用object來(lái)實(shí)現(xiàn)枚舉功能
Scala沒有直接提供類似于Java中的Enum這樣的枚舉特性瘾婿,如果要實(shí)現(xiàn)枚舉蜻牢,則需要用object繼承Enumeration類烤咧,并且調(diào)用Value方法來(lái)初始化枚舉值
object Season extends Enumeration {
val SPRING, SUMMER, AUTUMN, WINTER = Value
}
println(Season.SPRING)
println(Season.SUMMER)
println(Season.AUTUMN)
println(Season.WINTER)
還可以通過(guò)Value傳入枚舉值的id和name,通過(guò)id和toString可以獲取; 還可以通過(guò)id和name來(lái)查找枚舉值
object Season extends Enumeration {
val SPRING = Value(0, "SPRING")
val SUMMER = Value(1, "SUMMER")
val AUTUMN = Value(2, "AUTUMN")
val WINTER = Value(3, "WINTER")
}
println(Season(0))
println(Season.withName("SPRING"))
使用枚舉object.values可以遍歷枚舉值
for(ele <- Season.values) {
println(ele)
}