提出问题:有一群小朋友在玩堆雪人,不时有新的小朋友加入,请问如何计算现在有几个小朋友?【使用面向对象的思想】
初步分析:
- 在 Java 中,可以使用静态属性解决该问题,即通过类对象调用,这种操作不是面向对象的
- 然而 Scala 是完全面向对象的,所以并没有静态相关的操作,这就需要提出解决办法
进一步分析:为了和 Java 无缝衔接,Scala 就使用了一种特殊的对象来模拟类,我们称之为伴生对象
案例研究
object AccompanyObject {
def main(args: Array[String]): Unit = {
val c1 = new Child("zhangsan")
c1.showInfo
Child.showInfo(c1)
// c1.age 无法访问
val c2 = new Child("lisi")
Child.joinGame(c1)
Child.joinGame(c2)
println("total: " + Child.total)
}
}
// 伴生对象
object Child {
var total = 0
def showInfo(c: Child): Unit = {
println(s"object Child: name=${c.name}, age=${c.age}")
}
def joinGame(c: Child): Unit = {
println(s"${c.name} 加入游戏!")
total += 1
}
}
// 伴生类
class Child(inName: String) {
var name: String = inName
private var age: Int = _
def showInfo: Unit = {
println(s"class Child: name=$name, age=$age")
}
}
语法介绍
定义:在同一个文件中,以“object”关键字声明的称为伴生对象,和它同名的“class xxx”称为伴生类
区别:
- 伴生对象中是静态内容,伴生类中是非静态内容(存放内容性质不同)
- 伴生对象中的属性和方法通过类名访问,伴生类中的通过该类实例访问(访问方式不同)
📝 注意点
- 伴生对象和伴生类的声明必须在同一个源文件中,否则运行发生错误
- 如果伴生对象单独存在,那么它就是一个“静态”性质的对象,即类对象
- 如果伴生类单独存在,那么它就是一个普通的类
✍ 底层原理是如何实现的?
- “object Child”对应 Child$.classChild$.java
- “class Child”对应 Child.classChild.java
- 访问机制AccompanyObject$.java
apply方法
在伴生对象中可以定义 apply 方法,可以实现“类名(参数)”的方式创建对象,具体参考一下的案例 ```scala // 自行测试 object Test { def main(args: Array[String]): Unit = { // 使用 apply 方式创建对象 val p = Pig(“小黑”) // 自动触发apply(name: String) println(p) // 实际使用的是 toString 方法 } }
object Pig { def apply(name: String): Pig = new Pig(name) def apply(): Pig = new Pig(“小花”) }
class Pig(pName: String) { var name: String = pName // 重写 toString 方法 override def toString: String = this.name } ```