开发者学堂课程【Scala 核心编程-基础:伴生对象使用细节和最佳实践】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8985
伴生对象使用细节和最佳实践
内容介绍
一、伴生对象的使用细节
二、案例讲解
一、伴生对象的使用细节
对于伴生对象的使用细节,本章节总共总结了九点,如下:
1、Scala 中伴生对象采用 object 关键字声明,伴生对象中声明的全是"静态"内容,可以通过伴生对象名称直接调用。意识就是说静态内容就是模拟的,对于是怎么模拟的通过下面的流程图进行讲解:
如图所有实现的静态都是围绕这个 MODULE,也就是说可以创建很多的 ScalaPerson,数量不限制,但是Scala 里面的静态内容只能通过他的伴生对象中类的 MODULE 去调用,而 MODULE 是一个 static 类型,相当于只有一个,而静态的本质也只有一个。只要访问 ScalaPerson 中的内容,入口只有一条线,这条线就是 static final MODULE$,所以就能保证实现的是静态效果。
2、伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。那么如果把 ScalaPerson 改为ScalaPerson2,那么 ScalaPerson 和 ScalaPerson2就没有关系了,而此时编译后 ScalaPerson2在底层会生成ScalaPerson2.class,ScalaPerson 会默认生成空的 ScalaPerson.class 和 ScalaPerson$.class。代码如下:
//伴生类
class Scalaperson { //底层 ScalaPerson2.class
var name : String =_
}
//伴生对象
object ScalaPerson { //默认ScalaPerson.class ScalaPerson$. class
var sex : Boolean = true
def sayHi(): Unit = {
println("object ScalaPerson sayHI~~" )
}
}
3、伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。比如如下流程图就是通过伴生名称ScalaPerson.sayHi()进行调用的,而底层是用伴生对象类里面对应的那一个 MODULES 静态属性进行调用的。
4、从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合
5、从技术角度来讲,scala 还是没有生成静态的内容,只不过是将伴生对象生成了一个新的类,实现属性和方法的调用。对于 Scala 并没有生成静态的内容是因为伴生对象中生成的都是静态内容,代码如下:
object ScalaPerson { //
var sex : Boolean = true
def sayHi(): Unit = {
pridtln("object ScalaPerson sayHI~")
}}
而代码中 sex 和 sayHi()在底层生成的并不是静态的,仍然是一个普通的属性,反编译看源码为:
package com. atguigu. chapter08;
…
public static final MODULES:
…
private boolean
s
ex;
…
public void sayHi() {
…
所以并没有生成静态内容,只是调用了 static final MODULES 完成了静态效果。
6、从底层原理看,伴生对象实现静态特性是依赖于 public static final MODULES 实现的。
7、伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!),但是如果没有伴生类,也就没有所谓的伴生对象了,所以放在哪里就无所谓了。
8、如果 classA 独立存在,那么A就是一个类,如果 object A 独立存在,那么 A 就是一个"静态"性质的对象[即类对象],在 objectA 中声明的属性和方法可以通过 A.属性和 A.方法来实现调用
9、当一个文件中,存在伴生类和伴生对象时,文件的图标会发生变化。如下图,当文件中内容只有class Test 时,最左 Project 板块中 Test 目录图标为全蓝色,而添加内容 object Test 后,图标改变为一半蓝一半黄,说明文件中有伴生对象和伴生类:
二、案例讲解
下面使用伴生对象快速解决小孩完游戏案例
案例:如果设计一个 var total Int 表示总人数,在创建一个小孩时,就把 total 加1,并且 total 是所有对象共享的就可以,下面使用伴生对象来解决。
实现代码:
package com. atguigu. chapter08
object ChildJoinGame {
def main(args: Array[String]): Unit = {
//创建三个小孩
val child0 = new Child02("白骨精")
val child1 = new Child02("蜘蛛精" )
val child2 = new Child02(" 黄鼠狼精")
Child02. joinGame( child0)
//创建小孩,让小孩加入到游戏中
Child02. joinGame(child1)
Child02. joinGame( child2)
Child02. showNum()
//输出总共的小孩,理论上为3个
}}
class Child02(cName: String) {
//因为有很多小孩,而且每个小孩都有名字,所以再写上主构造器
var name =
c
Name
//定义变量为 name,赋值为 cName
object Child02 {
//统计共有多少小孩的属性
var totalChildNum = 0
def joinGame(child: Child02): Unit = {
//定义 joinGame用于接收小孩
printf("%s小孩加入了游戏\n",child .name )
//然后进行格式提示信息
//totalchildNum加1
totalchildNum += 1
}
def showNum(): Unit = {
//定义静态方法为 showNum
printf(" 当前有%d小孩玩游戏\n",totalChildNum)
}}
运行结果:
D: \program\jdk8\bin\java
白骨精 小孩加入了游戏
蜘蛛精 小孩加入了游戏
黄鼠狼精 小孩加入了游戏
当前有3小孩玩游戏