一、单例对象(singleton object)
单例对象提供了和Java静态成员同样的功能。
静态的好处是只要定义了一个单例对象不用去实例化就可以去使用成员字段。
object Person {
private var lastId = 0 //一个人的身份证编号
def newPersonId() = {
lastId += 1
lastId
}
def main(args: Array[String]): Unit = {
printf("The first person id: %d.\n",Person.newPersonId())
printf("The second person id:%d.\n",Person.newPersonId())
printf("The third person id: %d.\n",Person.newPersonId())
}
}
out:
The first person id: 1.
The second person id:2.
The third person id: 3.
单例对象可分为:
- 伴生对象
在同样一个代码文件当中,同时出现class A
和object A
;它们的类名和对象名完全相同,它们就互为伴生关系;这个类就称为这个单例对象的伴生类,这个单例对象就称为这个类的伴生对象。
而且它们互为伴生关系,故它们彼此可以访问对方内部成员。 - 孤立对象
类名和对象名不相同的则为孤立对象。
class Person2(val name: String) {
private val id = Person2.newPersonId() //调用了伴生对象中的方法
def info(): Unit = {
printf("The id of %s is %d.\n", name, id)
}
}
object Person2 {
private var lastId = 0 //一个人的身份证编号
def newPersonId() = {
lastId += 1
lastId
}
def main(args: Array[String]): Unit = {
val person01 = new Person2("Lilei")
val person02 = new Person2("Hanmei")
person01.info()
person02.info()
}
}
out:
The id of Lilei is 1.
The id of Hanmei is 2.
二、apply方法
val myStrArr = Array("BigData","Hadoop","Spark")
//Scala调用Array这个类的伴生对象
apply方法调用的约定:
用括号传递给类实例或单例对象名一个或多个参数时;
Scala 会在相应的类或对象中查找方法名为apply;
且参数列表与传入的参数一致的方法;
并用传入的参数来调用该apply方法。
class TestApplyClass {
def apply(param: String): Unit = {
println("apply method caled:" + param)
}
}
object TestApplyClass_test {
def main(args: Array[String]): Unit = {
val myObject = new TestApplyClass
myObject("Hello Apply")
//自动调用类中定义的apply方法,等同于下句
myObject.apply("Hello Apply")
//手动调用apply方法
}
}
out:
apply method caled:Hello Apply
apply method caled:Hello Apply
apply方法不断生成对象(工厂对象),把所有类的构造方法以apply方法的形式定义在它的伴生对象当中。
一个class一个类
给类定义一个伴生对象
类的构造方法以apply方法的形式写在伴生对象中
伴生对象的方案会被自动调用
调用会自动生成类对象
class Car(name: String) {
def info(): Unit = {
println("Car name is" + name)
}
}
object Car {
def apply(name: String) = new Car(name)
//调用伴生类Car的构造方法
}
object MyTestApply {
def main(args: Array[String]): Unit = {
val mycar = Car("BMW") //调用伴生对象中的apply方法
mycar.info()
}
}
out:
Car name isBMW
使用apply的目的是实现对象和函数的一致性。
既保留括号调用形式也保留点号调用形式。
三、update方法
Update方法遵循相应的调用约定:
当对带有括号并包括一到若干参数的对象进行赋值时;
编译器将调用对象的update方法;
并将括号里的参数和等号右边的值;
一起作为update方法的输入参数来执行调用。
scala> val myStrArr = new Array[String](3)
//声明一个长度为3的字符串数组,每个数组元素初始化为null
scala> myStrArr(0)= "BigData"
//实际上,调用了伴生类Array中的update方法,执行myStrArr.update(0,"BigData")
四、unapply方法
unapply是反向解构的过程,提取参数。
class Car2(val brand: String, val price: Int) {
def info(): Unit = {
println("Car brand is" + brand + "and price is" + price)
}
}
object Car2 {
def apply(brand: String, price: Int) = {
println("Debug:calling apply...")
new Car2(brand, price)
}
def unapply(c: Car2): Option[(String, Int)] = {
println("Debug:calling unapply...")
Some((c.brand, c.price))
}
}
object TestUnapply {
def main(args: Array[String]): Unit = {
var Car2(carbrand, carprice) = Car2("BMW", 800000)//右边调用apply;左边调用unapply.先运行右边再运行左边
println("carbrand:" + carbrand + " and carprice" + carprice)
}
}
out:
ebug:calling apply...
Debug:calling unapply...
carbrand:BMW and carprice800000