伴生对象使用细节和最佳实践|学习笔记

简介: 快速学习伴生对象使用细节和最佳实践。

开发者学堂课程【Scala 核心编程-基础伴生对象使用细节和最佳实践】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/609/detail/8985


伴生对象使用细节和最佳实践

 

内容介绍

一、伴生对象的使用细节

二、案例讲解

 

一、伴生对象的使用细节

对于伴生对象的使用细节,本章节总共总结了九点,如下:

1Scala 中伴生对象采用 object 关键字声明,伴生对象中声明的全是"静态"内容,可以通过伴生对象名称直接调用。意识就是说静态内容就是模拟的,对于是怎么模拟的通过下面的流程图进行讲解:

image.png

如图所有实现的静态都是围绕这个 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 静态属性进行调用的。

image.png

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 sex;

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 后,图标改变为一半蓝一半黄,说明文件中有伴生对象和伴生类:

image.png

image.png

 

二、案例讲解

下面使用伴生对象快速解决小孩完游戏案例

案例:如果设计一个 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 = cName  //定义变量为 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小孩玩游戏

相关文章
|
6月前
|
Java 程序员
深入理解Java匿名内部类的语法和使用场景
深入理解Java匿名内部类的语法和使用场景
|
8月前
|
存储 安全 Java
源码必备知识:泛型
源码必备知识:泛型
51 2
|
7月前
|
存储 安全 编译器
C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)
C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)
54 0
|
8月前
|
算法 Serverless 数据安全/隐私保护
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
501 1
|
编译器 C语言 C++
C嘎嘎~~ [类 下篇之运算符重载]
C嘎嘎~~ [类 下篇之运算符重载]
|
Java
Java面向对象进阶6——权限修饰符(含源码阅读)
在上面举例的代码中,brand , colour两个变量是没用访问修饰符的,但是可以在同一个包的测试类中使用是不会报错的,但是如果使用别的包中的类就会报错
110 0
Java面向对象进阶6——权限修饰符(含源码阅读)
java接口的基本介绍与使用细节
java接口的基本介绍与使用细节
|
设计模式 Java 数据库连接
对象构造神器,建造者模式实操分享
建造者模式,简单的说,就是将对象的属性与创建分离,使得同样的构建过程可以创建不同的对象。 初次接触这个概念,可能有点闷逼,下面我们来举例,你就好懂了! 假设有一个对象里面有20个属性,如果我要使用这个对象,我们可能需要把这20个属性弄明白,然后在构造函数或者创建一个对象通过set一个一个去指定,显然这对开发者来说非常吃力!
对象构造神器,建造者模式实操分享
Java泛型的简单使用
Java泛型使用比较广泛,自己定义接口的时候很容易用到,所以记录一下,方便查阅。比较简单,简单实用足够了
|
Java 编译器 C++
“生而有值”—教你使用构造函数 | 带你学《Java面向对象编程》之五
本节结合多组实例从多个方面介绍了重写构造函数的意义以及构造函数与setter函数的异同,指出了一些编写构造函数相关的注意事项。
“生而有值”—教你使用构造函数   | 带你学《Java面向对象编程》之五