Все объекты являются одиночками (Singleton Object) - то есть существуют в единственном экземпляре. Он создается лениво, когда на него ссылаются, также как ленивые значения (lazy val).
На самом верхнем уровне объект является одиночкой.
Как член класса или как локальная переменная, он ведет себя точно так же как ленивое значение (lazy val).
Объявление одиночного объекта
Объект - является значением. Объявление объекта происходит схожим с классом образом, но используется ключевое слово object
:
object Box
Вот пример объекта с методом:
package logging
object Logger {
def info(message: String): Unit = println(s"INFO: $message")
}
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
class Project(name: String, daysToComplete: Int)
class Test:
val project1 = Project("TPS Reports", 1)
val project2 = Project("Website redesign", 5)
info("Created projects") // Prints "INFO: Created projects"
Метод info
виден благодаря указанию импорта import logging.Logger.info
.
Для импорта требуется “постоянный путь” к импортируемому символу, а путь к объекту неизменен.
Замечание: Если object
не является объектом верхнего уровня, но вложен в другой класс или объект,
то объект, как и любой другой член, “зависим от пути”.
Это означает, что для двух видов напитков, class Milk
и class OrangeJuice
,
элемент класса object NutritionInfo
“зависит” от включающего его экземпляра, будь то Milk
или OrangeJuice
.
milk.NutritionInfo
полностью отличается от oj.NutritionInfo
.
Объекты компаньоны
Объект с тем же именем, что и класс называется объект компаньон (companion object). И наоборот, класс является классом-компаньоном объекта. Класс или объект компаньон может получить доступ к приватным членам своего спутника. Используйте объект компаньон для методов и значений, которые не специфичны для экземпляров класса компаньона.
import scala.math.pow
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
import scala.math.pow
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
, который специфичен для каждого конкретного экземпляра, а метод calculateArea
одиночного объекта Circle
, доступен для каждого экземпляра класса Circle
.
Объект компаньон может также содержать методы создающие конкретные экземпляры класса спутника:
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}
""".stripMargin)
case None => println("Error: could not parse email")
}
class Email(val username: String, val domainName: String)
object Email:
def fromString(emailString: String): Option[Email] =
emailString.split('@') match
case Array(a, b) => Some(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}
""".stripMargin)
case None => println("Error: could not parse email")
object Email
содержит производящий метод fromString
, который создает экземпляр Email
из строки. Мы возвращаем результат как Option[Email]
на случай возникновения ошибок парсинга.
Примечание: Если у класса или объекта есть компаньон, они должны быть размещены в одном и том же файле. Чтобы задать компаньонов в REPL, либо определите их на той же строке, либо перейдите в режим :paste
.
Примечания для Java-программистов
static
члены в Java смоделированы как обычные члены объекта компаньона в Scala.
При использовании объекта компаньона из Java-кода, члены будут определены в сопутствующем классе компаньоне с static
модификатором. Это называется пробрасывание статики. Такое происходит, даже если вы сами не определили класс компаньон.
Дополнительные ресурсы
- Узнайте больше об объектах компаньонах в Scala Book
Contributors to this page:
Contents
- Введение
- Основы
- Единобразие типов
- Классы
- Значения Параметров По умолчанию
- Именованные Аргументы
- Трейты
- Кортежи
- Композиция классов с трейтами
- Функции Высшего Порядка
- Вложенные Методы
- Множественные списки параметров (Каррирование)
- Классы Образцы
- Сопоставление с примером
- Объекты Одиночки
- Регулярные Выражения
- Объект Экстрактор
- Сложные for-выражения
- Обобщенные Классы
- Вариантность
- Верхнее Ограничение Типа
- Нижнее Ограничение Типа
- Внутренние классы
- Члены Абстрактного Типа
- Составные Типы
- Самоописываемые типы
- Контекстные параметры, также известные, как неявные параметры
- Неявные Преобразования
- Полиморфные методы
- Выведение Типа
- Операторы
- Вызов по имени
- Аннотации
- Пакеты и Импорт
- Объекты Пакета