scala之旅-核心语言特性【单例对象】(十五)

object 是一个类有且唯一的实例。当对象被引用时,它是懒模式创建的,就像 lazy val一样。

作为一个顶级的值,对象是单例的。

作为一个封闭类的成员或者局部值时,它的行为更像是一个lazy val。

定义一个单例的对象

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

object Box

下面是一个关于对象的例子,这个对象有一个方法:

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语句 import logging.Logger.info,info方法就可以被访问。

import 需要一个全路径,对象也是全路径导入。

注意:如果一个对象不是顶级的,但是是内嵌在其他类或者对象里面的,那么这个对象的需要用 全路径+依赖的方式,与类其他成员访问方式一样。这意味着给定两种饮料类,类 Milk和类 OrangeJuice, 一个类成员 object NutritionInfo 依赖于封闭的实例,无论是 milk 还是 orangeJuice,milk.NutritionInfo 和 oj.NutritionInfo 都是不一样的。

对象的比较

与类同名的对象称之为伴生对象。相反,这个类称之为伴生类。伴生类或对象可以访问与其伴生的内部私有成员。将伴生对象用于伴生类实例中没有指明的方法和值。

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)
}

val circle1 = Circle(5.0)

circle1.area

这里的类 Circle有一个在实例指定的area成员,单例对象Circle有一个 calculateArea方法,这个方法每个实例都可以访问。

伴生对象当然也可以包含工厂方法:

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
    }
  }
}

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}
     """.stripMargin)
  case None => println("Error: could not parse email")
}

这个对象 Email 包含一个工厂 fromString 用来从一个字符串中创建一个Email。 以防解析错误,我们用一个 Option[Email] 返回。

注:如果一个类或对象有伴生,那么它们必须在一个文件里面定义。要在REPL中定义伴生,请在同一行上定义它们或进入:paste模式 【注:这句话我没看懂~】

Java开发者注意

java的static 成员被建模在scala的伴生对象的普通成员。

当从java代码中使用伴生对象时,伴生对象成员将会在伴生类里面用一个static进行定义。这叫做静态转化,这个一般出现在即使你没有定义伴生类的时候。

原文地址:https://www.cnblogs.com/zhouwenyang/p/13891622.html