2、Scala 对象
2.1、单例对象
在某些应用场景下,我们可能不需要创建对象,而是想直接调用方法,但是 Scala 语言并不 支持静态成员,没有静态方法和静态字段,Scala 通过单例对象 object 来解决该问题
1、存放工具方法和常量
2、高效共享单个不可变的实例
3、单例模式
package com.mazh.scala.day2.oop
import scala.collection.mutable.ArrayBuffer
/**
* 作者: 李涛 https://blog.csdn.net/qq_42246689
*/
object SingletonDemo {
def main(args: Array[String]) {
// 单例对象,不需要 new ,用【类名 . 方法】调用对象中的方法
val session = SessionFactory.getSession()
println(session)
}
}
object SessionFactory{
// 该部分相当于 java中的静态块
var counts = 5
val sessions = new ArrayBuffer[Session]()
while(counts > 0){
sessions += new Session
counts -= 1
}
// 在 object中的方法相当于 java中的静态方法
def getSession(): Session ={
sessions.remove(0)
}
}
class Session{
}
总结:
1、object 里面的方法都是静态方法
2、object 里面的字段都是静态字段
3、它本身就是一个单例,(因为不需要去 new)
2.2、伴生对象
在 Scala 的类中,与类名相同的单例对象叫做伴生对象,也就是说如果我们在 object Dog 所 在的文件内定义了一个 class Dog,此时:
1、 object Dog 被称为 class Dog 的伴生对象
2、 class Dog 被称为 object Dog 的伴生类
3、 类和伴生对象之间可以相互访问私有的方法和属性
package com.mazh.scala.day2.oop
/**
* 作者: 李涛 https://blog.csdn.net/qq_42246689
*/
class Dog {
val id = 100
private var name = "旺财"
def printName(): Unit ={
// 在 Dog类中可以访问伴生对象 Dog的私有属性
println(Dog.CONSTANT + name )
}
}
/**
* 伴生对象
*/
object Dog {
// 伴生对象中的私有属性
private val CONSTANT:String = "汪汪汪: "
def main(args: Array[String]) {
val p = new Dog
// 访问私有的字段 name
p.name = "123"
p.printName()
}
}
总结: 伴生类 和 伴生对象 之间可以互相访问对方的私有属性
2.3、Apply 方法
在讲集合和数组的时候,可以通过 val intList=List(1,2,3)这种方式创建初始化一个列表对象, 其实它相当于调用 val intList=List.apply(1,2,3),只不过 val intList=List(1,2,3)这种创建方式更简 洁一点,但我们必须明确的是这种创建方式仍然避免不了 new,它后面的实现机制仍然是 new 的方式,只不过我们自己在使用的时候可以省去 new 的操作。通常我们会在类的伴生 对象中定义 apply 方法,当遇到【类名(参数 1,...参数 n)】时 apply 方法会被调用。
package com.mazh.scala.day2.oop
object ApplyDemo {
def main(args: Array[String]) {
// 调用了 Array伴生对象的 apply方法
//def apply(x: Int, xs: Int*): Array[Int]
//arr1 中只有一个元素 5
val arr1 = Array(5)
println(arr1.toBuffer)
//new了一个长度为 5的 array ,数组里面包含 5个 null
var arr2 = new Array(5)
println(arr2.toBuffer)
}
}
缺点: 无法为该类的执行,从外部传入参数,也既没有 main 方法的参数可用
2.4、应用程序对象 App
Scala 程序都必须从一个对象的 main 方法开始,可以通过扩展 App 特质,不写 main 方法。
package com.mazh.scala.day2.oop
/**
* 作者: 李涛 https://blog.csdn.net/qq_42246689
*/
object AppObjectDemo extends App{
// 不用写 main方法
println("I love Scala")
}
缺点: 无法为该类的执行,从外部传入参数,也既没有 main 方法的参数可用
2.5、抽象类
抽象类是一种不能被实例化的类,抽象类中包括了若干不能完整定义的方法,这些方法由子 类去扩展定义自己的实现。
1、如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现自 己不同的方法实现。此时可以将父类中的这些方法不给出具体的实现,只有方法签名,这 种方法就是抽象方法。
2、而一个类中如果有一个抽象方法,那么类就必须用 abstract 来声明为抽象类,此时抽象 类是不可以实例化的
3、在子类中覆盖抽象类的抽象方法时,不需要使用 override 关键字
package com.mazh.scala.day2.oop
/**
* 作者: 李涛 https://blog.csdn.net/qq_42246689
* 描述: 定义抽象类
*/
abstract class Animal {
// 抽象字段 ( 域)
// 前面我们提到,一般类中定义字段的话必须初始化,而抽象类中则没有这要求
var height:Int
// 抽象方法
def eat:Unit
}
//Person继承 Animal ,对 eat方法进行了实现
// 通过主构造器对 height参数进行了初始化
class Person(var height:Int) extends Animal{
// 对父类中的方法进行实现,注意这里面可以不加 override关键字
def eat()={
println("eat by mouth")
}
}
总结: Scala 抽象类的使用方式和 Java 中的抽象类的概念一致