博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala编程之伴生对象
阅读量:6402 次
发布时间:2019-06-23

本文共 3207 字,大约阅读时间需要 10 分钟。

伴生对象是scala中静态的概念

Scala语言是完全面向对象(万物皆对象)的语言,所以并没有静态的操作(即在 Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,我们称之为类的伴生对象。这个类的所有静态内容都可以放置在它的伴生对象中声明和调用。

伴生对象的使用

下面我们通过一个小案例,对伴生对象和伴生类的特点进行探讨

//首先我们创建伴生类class ScalaPerson和伴生对象 object ScalaPerson,然后在里面设置几个方法和属性object AccompanyObject {  def main(args: Array[String]): Unit = {    println(ScalaPerson.sex) //true   底层等价于ScalaPerson$.MODULE$.sex    ScalaPerson.sayHi  //object ScalaPerson sayHi  底层等价  ScalaPerson$.MODULE$.sayHi()  }}//说明://当在一个文件之后有class ScalaPerson 和object ScalaPerson//class ScalaPerson被称为object ScalaPerson的伴生类,我们常常把非静态内容写进该类中//object ScalaPerson被称为class ScalaPerson的伴生对象,将静态内容写入该对象中//class ScalaPerson在底层被编译为class ScalaPerson.class//object ScalaPerson在底层被编译为class ScalaPerson$.classclass ScalaPerson{  var name:String=_}object ScalaPerson{  val sex:Boolean=true  def sayHi: Unit ={    println("object ScalaPerson sayHi")  }}

反编译看源码

Scala编程之伴生对象

小结

  1. Scala中伴生对象采用 object关键字声明,伴生对象中声明的全是"静态"内容,可以通过伴生对象名称直接调用。
  2. 伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
  3. 伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问
  4. 从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合
  5. 从技术角度来讲, scala还是没有生成静态的内容,只不过是将伴生对象生成了一个新的类,实现属性和方法的调用。[反编译看源码]
  6. 从底层原理看,伴生对象实现静态特性是依赖于 public static final MODULE$实现的
  7. 伴生对象的声明应该和伴生类的声明在同一个源码文件中(如果不在同一个文件中会运行错误!),但是如果没有伴生类,也就没有所谓的伴生对象了,所以放在哪里就无所谓了。
  8. 如果 class A独立存在,那么A就是一个类,如果 object A独立存在,那么A就是一个"静态性质的对象[即类对象],在 object A中声明的属性和方法可以通过A.属性和A.方法来实现调用
  9. 当一个文件中,存在伴生类和伴生对象且不存在其他类时,文件的图标会发生变化Scala编程之伴生对象

    apply方法

    apply方法是非常常用的,它主要的作用就是简化创建对象的写法

    //创建一个List集合val list=List(("A",0),("A",2),("B",1),("B",2),("C",1))

    我们创建list的时候,并没有new 创建对象,也没有通过反射创建对象,那么为什么直接List()就可以创建一个list集合呢?答案就在List()底层实现了apply()方法

    我们可以Ctrl +鼠标左键点击ListScala编程之伴生对象
    可以看到,底层实现了apply方法
    我们现在来实际使用一下apply方法吧

object ApplyDemo extends App {  //使用apply方法创建对象  val pig1=Pig("佩奇") // 自动触发apply(pname: String)  val pig2=Pig()     //自动触发apply()  printf("小猪1为%s \n",pig1.name)//小猪1为佩奇  printf("小猪2为%s \n",pig2.name)//小猪2为匿名Pig}class Pig(pname:String){  var name=pname}object Pig{  def apply(pname: String): Pig = new Pig(pname)   //自动生成  def apply():Pig=new Pig("匿名Pig")    //重载方法}

apply在实际生产中使用的特别多,虽然简单,但是很重要。

总结:
1)类名()==>调用的是伴生对象中的aplly方法 常用
2)对象()==>调用的是伴生类中的apply方法 不常用
3)类名()看似不用new对象了,但是其实底层一定是通过apply方法创建了一个对象并返回。

我们可以利用本文的知识完成下面的问题~练练手~

下面的题,是一道java题,请使用scala完成该题的要求1)在 Frock类中声明私有的静态属性 currentNum,初始值为100000,作为衣服出厂的序列号起始值。2)声明公有的静态方法 getNextNum,作为生成上衣唯一序列号的方法。每调用一次,将 currentNum增加100,并作为返回值3)在 TestFrock类的main方法中,分两次调用 getNextNum方法,获取序列号并打印输出4)在Frock类中声明 serialNumber(序列号)属性,并提供对应的get方法;5)在Frock类的构造器中,通过调用 getNextNum方法为Frock对象获取唯一序列号,赋给 serialNumbe属性。6)在 TestFrock类的main方法中,分别创建三个 Frock对象,并打印三个对象的序列号,验证是否按100递增

代码仅供参考~如有更好的建议请联系企鹅:1176738641

object TestFrock {  def main(args: Array[String]): Unit = {    val frockList=List(Frock(),Frock(),Frock())    for (frock<-frockList){      println(frock.getSerialNumber())    }  }}class Frock(){  private [this] var serialNumber:Int= _  def getSerialNumber():Int={    this.serialNumber  }  def setSerialNumber(num:Int): Unit ={    this.serialNumber=num  }}object Frock{  private var currentNum=100000  def apply(): Frock = {    val frock=new Frock()    frock.setSerialNumber(getNextNum())    frock  }   def getNextNum() :Int={    currentNum=currentNum+100    currentNum  }}

转载于:https://blog.51cto.com/14309075/2393082

你可能感兴趣的文章
linux find 命令忽略某个或多个子目录的方法
查看>>
Linux命令总结(部分说明)
查看>>
radmin自动安装
查看>>
IP子网划分的原理及应用
查看>>
系统变量与自定义变量
查看>>
分久必合:APU是一种发展趋势
查看>>
SCCM2012升级SP1系列之部署SCCM2012①准备系统架构和数据库
查看>>
lograte
查看>>
在Linux系统中文件(资源)和用户的管理
查看>>
IntelAMT 固件密码绕过登录漏洞分析与实战
查看>>
ansible自动化管理windows系统实战
查看>>
AgileEAS.NET之数据关系映射ORM
查看>>
Jquery封装tab自动切换效果
查看>>
Iperf安装使用及测试专线带宽
查看>>
抢先体验IE9
查看>>
【斗医】【16】Web应用开发20天
查看>>
javascript 基本使用—字符串、变量、数组、函数、for循环
查看>>
[C# 开发技巧]实现属于自己的截图工具
查看>>
mysql基础调优
查看>>
CYQ.Data 快速开发之UI(赋值、取值、绑定)原理
查看>>