Scala之旅(TOUR OF SCALA)——单例对象(SINGLETON OBJECTS)

一个对象是一个只有一个实例的类。当它在被引用时将使用懒加载,就像一个懒加载的常量(只有要使用这个常量时,它才会被加载)。

作为一个顶级变量,一个对象就是一个单例。

作为一个类或局部变量的成员,它的行为几乎与就像一个懒加载的常量相同。

定义一个单例对象 (Defining a singleton object)

一个对象就是一个值。定义一个对象就像定义一个类一样。但是使用 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 logging.Logger.info 导入了 info 方法,所以可以直接使用。

导入需要一个“确定的路径”,而每一个对象都有一个确定的路径。

注意:如果一个对象不是顶级变量,而是在另一个类或对象内部,这个对象就是其它成员一样是“路径依赖”的。意思是说:如果给了两个饮料类,class Milkclass OrangeJuice,一个类成员 object NutritionInfo “依赖”于任何一个饮料类的实例。milk.NutritionInfo 对象与 oj.NutritionInfo 对象是完全不同的两个对象。

伙伴对象 (Companion objects)

如果一个对象的名字与一个类的名字完全相同,那么这个对象被称为伙伴对象。相对地,那个类被称伙伴类。一个伙伴类或伙伴对象能访问其伙伴的私有成员。没有实例化的伙伴类可以其伙伴对象的所有方法和属性。

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 = new Circle(5.0)

circle1.area

Circle 类的每一个实例都有一个叫 area 的成员,而 object 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("[email protected]")
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 实例。当 case 语句中解析出错时,将返回一个 Option[Email] 实例。

注意:如果一个类或者一个对象有伙伴,就必须都定义在同一个文件中。在 RERL 中定义一对伙伴也必须定义在同一行中或者进行 :paste 模式。

对 Java 程序员的建议 (Notes for Java programmers)

在 Java 中静态( static )成员等同于 Scala 中伙伴对象中的普通成员。

当在 Java 代码中使用一个伙伴对象时,其成员将被定义其对应的伙伴类中并使用 static 关键字修饰。这叫作“静态转发”。它甚至发生在你根本没有定义对应的伙伴类时。

猜你喜欢

转载自blog.csdn.net/cuipp0509/article/details/79372169
今日推荐