|NO.Z.00032|——————————|BigDataEnd|——|Hadoop&Scala.V05|——|Scala.v05|类与对象|对象|
一、单例对象
### --- 单例对象
~~~ Scala并没有提供Java那样的静态方法或静态字段;
~~~ 可以采用object关键字实现单例对象,具备和Java静态方法同样的功能;
~~~ 使用object语法结构【object是Scala中的一个关键字】达到静态方法和静态字段的目的;
~~~ 对象本质上可以拥有类的所有特性,除了不能提供构造器参数;
### --- 对于任何在Java中用单例对象的地方,在Scala中都可以用object实现:
~~~ 作为存放工具函数或常量的地方
~~~ 高效地共享单个不可变实例
### --- 代码示例
class Session {
def hello(first: Int): Int = {
println(first)
first
}
}
object SessionFactory {
val session = new Session
def getSession(): Session = {
session
}
def main(args: Array[String]): Unit = {
for (x <- 1 to 10) {
//通过直接调用,产生的对象都是单例的
val session = SessionFactory.getSession()
println(session)
}
}
}
### --- Scala中的单例对象具有如下特点:
~~~ 创建单例对象不需要使用new关键字
~~~ object中只有无参构造器
~~~ 主构造代码块只能执行一次,因为它是单例的
object ObjectDemo {
println("这是单例对象的代码!")
def main(args: Array[String]): Unit = {
val object1=ObjectDemo
val object2=ObjectDemo
}
}
二、编程代码实现
### --- 编程代码
package yanqi.cn.part04
object Object {
println("这是单例对象的代码!")
def printInfo: Unit = {
println("Hello Scala Object!")
}
}
object ObjectDemo {
def main(args: Array[String]): Unit = {
// val object1=Object
// val object2=Object
Object.printInfo
Object.printInfo
}
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=55788:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part04.ObjectDemo
这是单例对象的代码!
Hello Scala Object!
Hello Scala Object!
Process finished with exit code 0
三、伴生类与伴生对象
### --- 伴生类与伴生对象
~~~ 当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”;
~~~ 类和它的伴生对象必须存在于同一个文件中,而且可以相互访问私有成员(字段和方法);
### --- 编程代码示例
class ClassObject {
val id = 1
private var name = "yanqi"
def printName(): Unit ={
//在ClassObject类中可以访问伴生对象ClassObject的私有字段
println(ClassObject.CONSTANT + name )
}
}
object ClassObject{
//伴生对象中的私有字段
private val CONSTANT = "汪汪汪"
def main(args: Array[String]) {
val p = new ClassObject
//访问伴生类的私有字段name
p.name = "123"
p.printName()
}
}
四、编程实现
### --- 编程代码
package yanqi.cn.part04
//伴生类和伴生对象,它们的名字是一样的,并且必须存在于同一文件中
class ClassObject {
private var name = "yanqi"
def printInfo: Unit = {
//在伴生类中可以访问伴生对象的私有成员
println(ClassObject.num)
println("Hello Object!")
}
}
object ClassObject {
private val num = 10
def main(args: Array[String]): Unit = {
val classObject = new ClassObject
//在伴生对象中可以访问伴生类的私有成员
println(classObject.name)
classObject.printInfo
}
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=55965:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part04.ClassObject
yanqi
10
Hello Object!
Process finished with exit code 0
五、应用程序对象
### --- 应用程序对象
~~~ 每个Scala应用程序都必须从一个对象的main方法开始,
~~~ 这个方法的类型为 Array[String] => Unit;
~~~ 备注:main方法写在class中是没有意义的,
~~~ 在IDEA中这样的 class 连run的图标都不能显示
~~~ 除了main方法以外,也可以扩展App特质(trait)
### --- 编程示例
object Hello extends App {
if (args.length > 0)
println(s"Hello World; args.length = ${args.length}")
else
println("Hello World")
}
六、编程实现
### --- 编程代码
package yanqi.cn.part04
object AppDemo extends App {
println("Hello Spark!")
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=55989:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part04.AppDemo
Hello Spark!
Process finished with exit code 0
七、apply方法
### --- apply方法:
~~~ object 中有一个非常重要的特殊方法 -- apply方法;
~~~ apply方法通常定义在伴生对象中,
~~~ 目的是通过伴生类的构造函数功能,来实现伴生对象的构造函数功能;
~~~ 通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用;
~~~ 在创建伴生对象或伴生类的对象时,通常不会使用new class/class() 的方式,
~~~ 而是直接使用class()隐式的调用伴生对象的 apply 方法,这样会让对象创建的更加简洁;
### --- 编程示例
//class Student为伴生类
class Student(name: String, age: Int) {
private var gender: String = _
def sayHi(): Unit ={
println(s"大家好,我是$name,$gender 生")
}
}
//object Student是class class的伴生对象
object Student {
//apply方法定义在伴生对象中
def apply(name: String, age: Int): Student = new Student(name, age)
def main(args: Array[String]): Unit = {
//直接利用类名进行对象的创建,这种方式实际上是调用伴生对象的apply方法实现的
val student=Student("jacky",30)
student.gender="男"
student.sayHi()
}
}
### --- 问题:在Scala中实现工厂方法,让子类声明哪种对象应该被创建,保持对象创建在同一位置。
~~~ 例如,假设要创建Animal工厂,让其返回Cat和Dog类的实例,基于这个需求,
~~~ 通过实现Animal伴生对象的apply方法,工厂的使用者可以像这样创建新的Cat和Dog实例。
abstract class Animal {
def speak
}
class Dog extends Animal {
override def speak: Unit = {
println("woof")
}
}
class Cat extends Animal {
override def speak: Unit = {
println("meow")
}
}
object Animal {
def apply(str: String): Animal = {
if (str == "dog")
new Dog
else
new Cat
}
def main(args: Array[String]): Unit = {
val cat = Animal("cat")
cat.speak
val dog = Animal("dog")
dog.speak
}
}
八、编程实现
### --- 编程代码
package yanqi.cn.part04
class Student(name: String, age: Int) {
private var gender: String = _
def sayHi(): Unit = {
println(s"大家好,我是$name,$gender 生")
}
}
object Student {
//apply方法需要定义在伴生对象中
def apply(name: String, age: Int): Student = new Student(name, age)
def main(args: Array[String]): Unit = {
//直接使用class(参数...)这种方式隐式调用伴生对象中的apply方法来创建class Student对象
val student = Student("jacky", 30)
//伴生类与伴生对象可以相互访问私有成员
student.gender = "男"
student.sayHi()
}
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=56017:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.10000——javaproject\NO.Z.00002.Hadoop\ScalaPro\out\production\ScalaPro;D:\JAVA\scala-2.12.2\lib\scala-library.jar;D:\JAVA\scala-2.12.2\lib\scala-reflect.jar yanqi.cn.part04.Student
大家好,我是jacky,男 生
Process finished with exit code 0
Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
——W.S.Landor
分类:
bdv015-scala
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通