Scala basic tutorial - what are singleton objects and associated classes?

A singleton object is a special class with only one instance. Like lazy variables, singleton objects are created late and only when they are first used.

When an object is defined at the top level (that is, it is not included in other classes), a singleton object has only one instance.

When an object is defined in a class or method, a singleton object behaves like an inert variable.

Define a singleton object

A singleton object is a value. A singleton object is defined in a way similar to a class, but the keyword object is used:

object Box

The singleton object in the following example contains a method:

package logging

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

The method info can be referenced anywhere in the program. Creating functional methods like this is a common use of singleton objects.

Let's see how to use the info method in another package:

// Because of the import statement, the method info is visible here.
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"
}

The import statement requires the imported ID to have a "stable path". A singleton object has a stable path because it is globally unique.

Note: if an object is not defined at the top level but in another class or singleton object, the singleton object is "path related" like other ordinary members of the class. This means that there are two behaviors, class Milk and class OrangeJuice. A class member object nutrioninfo "depends" on the instance that wraps it, either milk or orange juice. milk.NutritionInfo is completely different from OJ NutritionInfo.

Companion Object

In Scala, the usage of defining class and object with the same name in a source code file is called Companion.

  • Class objects are called companion classes, which are the same as classes in Java.
  • Object object is a singleton object, which is used to save some static variables or static methods. If you use Java, you must write two classes to implement, LogSegment and LogSegmentUtils. In Scala, you can use companion.

When a singleton object shares a name with a class, the singleton object is called an associated object. Similarly, this class is called the companion class of this singleton object. Class and its companion objects can access each other's private members. Use companion objects to define member variables or methods that do not depend on instantiated objects in the companion class.

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

The class Circle here has a member area, which is related to the specific instantiated object. The singleton object object Circle contains a method calculateArea, which is visible in each instantiated object.

Companion objects can also contain factory methods:

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

object Email {
  // The associated object object Email contains a factory method fromString 
  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}
     """)
  case None => println("Error: could not parse email")
}

Class and its associated objects must be defined in the same source file. If you need to define a class and its associated objects in REPL, you need to define them on the same line or enter the: paste mode.

Considerations for Java programmers

In Java, static members correspond to ordinary members of companion objects in Scala.

When a companion object is called in Java code, the members of the companion object will be defined as static members in the companion class. This is called static forwarding. This behavior occurs when you do not define an associated class yourself.

reference resources

  • https://docs.scala-lang.org/zh-cn/tour/singleton-objects.html

Tags: Scala

Posted by selenin on Tue, 17 May 2022 01:03:48 +0300