Scala之旅-单例对象(SINGLETON OBJECTS)

对象是一个只有一个实例的类。当它被引用的时候,它被懒惰地创建,就像一个懒惰的 val 一样。
作为顶级的值,对象是一个单例。
作为封闭类成员或本地值,它的行为表现的完全像是一个懒惰的 val。

定义单例对象

一个对象是一个值。对象的定义看起来像是一个类,但是使用的是关键字 object

object Box

下面是一个带方法对象的例子
新建 Logger.scala

package logging
object Logger {
  def info(message: String): Unit = println(s"INFO: $message")
}

方法 info 可以从程序的任何地方导入。创建这样的实用方法对于单例对象来说是常见的用法。

让我们看如何在另外一个包中使用 info 方法:

import logging.Logger.info
class Project(name: String, daysToComplete: Int)
class Test {
  val project1 = new Project("TPS Reports", 1)
  val project2 = new Project("Website redesign", 5)
  info("Created projects")  // Prints "INFO: Created projects"
}

这里写图片描述
因为有导入语句 import logging.Logger.info,所以 info 方法是可见的。导入需要一条“稳定路径”来导入名称标记,而对象就是一条稳定路径。

注意:如果一个 object 不是顶层的,而是嵌套在另一个类或是对象中。那么这个对象与任何其它成员一样都是“路径依赖”的。这是指给定两种饮料 class Milkclass OrangeJuiceobject NutritionInfo 是“依赖”于封闭实例的类内部成员,即 milkorange juice。那么 milk.NutritionInfooj.NutritionInfo 的结果是完全不同的。

伴生对象(Companion objects)

与类同名的对象称为伴生对象。相反,类是对象的伴生类。一个伴生类或对象可以访问同伴的私有成员。

对伴生对象使用不属于伴生类中的方法和值。
新建 Circle.scala

import scala.math._
case class Circle(radius: Double) {
  import Circle._
  def area: Double = calculateArea(radius)
}
object Circle {
  private def calculateArea(radius: Double): Double = Pi * pow(radius, 2.0)
}

这里写图片描述
idea中右击 run scala console,输入下面命令后按下组合键 ctrl + enter 运行:

val circle1 = new Circle(5.0)
circle1.area

这里写图片描述
class Circle 有一个特定于每个实例的成员 area,并且单例 object Circle 有一个方法 calculateArea,它对于每个实例都是可用的。

伴生对象也可以包含工厂方法:
新建 Email.scala

class Email(val username: String, val domainName: String)

object Email {
  def fromString(emailString: String): Option[Email] = {
    emailString.split('@') match {
      case Array(a, b) => Some(new Email(a, b))
      case _ => None
    }
  }
}

这里写图片描述
idea中右击 run scala console,输入下面命令后按下组合键 ctrl + enter 运行:

val scalaCenterEmail = Email.fromString("scala.center@epfl.ch")
scalaCenterEmail match {
  case Some(email) => println(
    s"""Registered an email
       |Username: ${email.username}
       |Domain name: ${email.domainName}
     """)
  case None => println("Error: could not parse email")
}

这里写图片描述
object Email 包含一个工厂方法 fromString,它用一个字符串创建 Email 实例。我们将其作为 Option[Email] 返回,以防解析错误。

注意:如果一个类或对象有一个同伴,那这两者必须定义在相同的文件中。如果要在 REPL 中定义伴生对象,要么把它们定义在同一行,要么进入 :paste 模式。

Java 程序员需要注意

Java 中的 static 成员被建模为 Scala 伴生对象的普通成员。

在 Java 代码中使用伴生对象时,会在伴生类中使用 static 修饰符定义成员 。这被称为静态转发 。即使你没有定义一个伴生类,也会发生这种情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值