Scala 3 — Book

Методы расширения

Language
Эта страница документа относится к Scala 3 и может охватывать новые концепции, недоступные в Scala 2. Если не указано явно, все примеры кода на этой странице предполагают, что вы используете Scala 3.

В Scala 2 аналогичного результата можно добиться с помощью неявных классов.


Методы расширения позволяют добавлять методы к типу после того, как он был определен, т.е. они позволяют добавлять новые методы в закрытые классы. Например, представьте, что кто-то создал класс Circle:

case class Circle(x: Double, y: Double, radius: Double)

Теперь представим, что необходим метод circumference, но нет возможности изменить исходный код Circle. До того как концепция вывода терминов была введена в языки программирования, единственное, что можно было сделать, это написать метод в отдельном классе или объекте, подобном этому:

object CircleHelpers {
  def circumference(c: Circle): Double = c.radius * math.Pi * 2
}
object CircleHelpers:
  def circumference(c: Circle): Double = c.radius * math.Pi * 2

Затем этот метод можно было использовать следующим образом:

val aCircle = Circle(2, 3, 5)

// без использования метода расширения
CircleHelpers.circumference(aCircle)

Но методы расширения позволяют создать метод circumference для работы с экземплярами Circle:

extension (c: Circle)
  def circumference: Double = c.radius * math.Pi * 2

В этом коде:

  • Circle — это тип, к которому будет добавлен метод расширения circumference
  • Синтаксис c: Circle позволяет ссылаться на переменную c в методах расширения

Затем в коде метод circumference можно использовать так же, как если бы он был изначально определен в классе Circle:

aCircle.circumference

Импорт методов расширения

Представим, что circumference определен в пакете lib - его можно импортировать с помощью

import lib.circumference

aCircle.circumference

Если импорт отсутствует, то компилятор выводит подробное сообщение об ошибке, подсказывая возможный импорт, например так:

value circumference is not a member of Circle, but could be made available as an extension method.

The following import might fix the problem:

   import lib.circumference

Обсуждение

Ключевое слово extension объявляет о намерении определить один или несколько методов расширения для типа, заключенного в круглые скобки. Чтобы определить для типа несколько методов расширения, используется следующий синтаксис:

extension (c: Circle)
  def circumference: Double = c.radius * math.Pi * 2
  def diameter: Double = c.radius * 2
  def area: Double = math.Pi * c.radius * c.radius

Contributors to this page: