Сопутствующие объекты
Объект, который имеет то же имя, что и класс, и объявлен в том же файле, что и класс, называется "сопутствующим объектом" (companion object). Аналогично, соответствующий класс называется сопутствующим классом объекта (companion class). Сопутствующий класс или объект может получить доступ к закрытым членам своего "соседа".
Сопутствующие объекты используются для методов и значений, которые не являются специфичными для экземпляров сопутствующего класса.
В следующем примере класс Circle
содержит метод с именем area
, который специфичен для каждого экземпляра.
А его сопутствующий объект содержит метод с именем calculateArea
,
который (а) не специфичен для экземпляра и (б) доступен для каждого экземпляра:
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 circle = Circle(5.0)
circle.area
// res0: Double = 78.53981633974483
В этом примере метод area
, доступный для каждого экземпляра Circle
, использует метод calculateArea
,
определенный в сопутствующем объекте.
Кроме того, поскольку calculateArea
является закрытым, к нему нельзя получить доступ с помощью другого кода,
но, как показано, его могут видеть экземпляры класса Circle
.
Другие виды использования сопутствующих объектов
Сопутствующие объекты могут использоваться для нескольких целей:
-
их можно использовать для группировки "статических" методов в пространстве имен, как в примере выше
- эти методы могут быть
public
илиprivate
- если бы
calculateArea
былpublic
, к нему можно было бы получить доступ из любого места какCircle.calculateArea
- эти методы могут быть
- они могут содержать методы
apply
, которые — благодаря некоторому синтаксическому сахару — работают как фабричные методы для создания новых экземпляров - они могут содержать методы
unapply
, которые используются для деконструкции объектов, например, с помощью pattern matching
Вот краткий обзор того, как методы apply
можно использовать в качестве фабричных методов для создания новых объектов:
class Person:
var name = ""
var age = 0
override def toString = s"$name is $age years old"
object Person:
def apply(name: String): Person = // одноаргументный фабричный метод
val p = new Person
p.name = name
p
def apply(name: String, age: Int): Person = // двуаргументный фабричный метод
val p = new Person
p.name = name
p.age = age
p
end Person
val joe = Person("Joe")
// joe: Person = Joe is 0 years old
val fred = Person("Fred", 29)
// fred: Person = Fred is 29 years old
Ссылки: