概念

Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。

使用object关键字, 声明出来的对象就是一个单例对象 独立对象 任何对象(object, 也可以是new), 只要提供了一个apply方法, 都可以
像使用方法一样去调用对象, 实际就是在调用apply
如果在同一个.scala文件中, 一个object的名字和一个class的名字一样, 则他们分别叫伴生对象和伴生类
编译成字节码之后, 伴生对象的是静态方法, 伴生类是非静态(对象方法).

伴生对象和伴生类

在Scala中, 同一个文件里面 一个类和一个对象名字是一模一样的.那么这就是伴生类和伴生对象
编译成字节码之后,伴生对象是静态方法,伴生类是非静态方法(对象方法)
伴生类和伴生对象可以配合使用,在日常开发的时候用的不多,但是在源码里面用的很多,伴生对象就相当于Java的静态方法.
伴生类和伴生对象可以互相访问对方的私有成员!!!
编译成字节码之后, 伴生对象中的成员变量就是java中的静态成员变量, 伴生类中的成员变量, 就是java中的普通成员变量.
伴生类和伴生对象的用法: 静态工厂

单例对象语法

  1. object Person{
  2. val country:String="China"
  3. }

(1)单例对象采用object关键字声明
(2)单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
(3)单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。

案例

//(1)伴生对象采用object关键字声明
object Person {
  var country: String = "China"
}

//(2)伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
class Person {
  var name: String = "bobo"
}

object Test {
  def main(args: Array[String]): Unit = {
    //(3)伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
    println(Person.country)
  }
}

apply方法

说明
(1)通过伴生对象的apply方法,实现不使用new方法创建对象。
(2)如果想让主构造器变成私有的,可以在()之前加上private。
(3)apply方法可以重载。
(4)Scala中obj(arg)的语句实际是在调用该对象的apply方法,即obj.apply(arg)。用以统一面向对象编程和函数式编程的风格。
(5)当使用new关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实时伴生对象的apply方法。

object Test {

  def main(args: Array[String]): Unit = {

    //(1)通过伴生对象的apply方法,实现不使用new关键字创建对象。
    val p1 = Person()
    println("p1.name=" + p1.name)

    val p2 = Person("bobo")
    println("p2.name=" + p2.name)
  }
}

//(2)如果想让主构造器变成私有的,可以在()之前加上private
class Person private(cName: String) {
  var name: String = cName
}

object Person {

  def apply(): Person = {
    println("apply空参被调用")
    new Person("xx")
  }

  def apply(name: String): Person = {
    println("apply有参被调用")
    new Person(name)
  }
}

静态工厂案例

import scala.collection.mutable


object Factory1 {
  def main(args: Array[String]): Unit = {
    println(Human.getHuman("黑色"))
    println(Human.getHuman("黑色"))


  }
}

object Human {

  val map = mutable.Map[String, Human](
    "黑色" -> new Human("黑色")
  )

  def getHuman(color: String) = map.getOrElseUpdate(color, new Human(color))
}

class Human private(color: String) {

  println(s"$color.....")

  override def toString: String = s"人种: $color"
}

输出

黑色.....
人种: 黑色
人种: 黑色