Модификаторы доступа Scala

В Scala модификаторы доступа используются для управления видимостью и правами доступа классов, объектов, трейтов и их членов (таких как поля и методы).

Модификаторы доступа Scala в основном такие же, как в Java: private, protected и public.

Если модификатор доступа не указан, по умолчанию уровень доступа в Scala — public.

Квалификатор private в Scala строже, чем в Java. В случае вложенных классов внешний класс не может даже получить доступ к private-членам вложенного класса.


Закрытые члены

Члены, помеченные ключевым словом private, видны только внутри класса или объекта, содержащего определение члена. То же правило также применяется к внутренним классам.

Пример

class Outer{
    class Inner{
        private def f(){
            println("f")
        }
        class InnerMost{
            f() // Верно
        }
    }
    (new Inner).f() // Ошибка
}

(new Inner).f( )Доступ запрещён, потому чтоfон объявлен как private в Inner, а доступ осуществляется не внутри класса Inner.

Но доступ к нему в InnerMostfдопустим, потому что этот доступ осуществляется внутри класса Inner.

Java позволяет оба доступа, потому что позволяет внешним классам получать доступ к private-членам внутренних классов.


Защищённые члены

В Scala доступ к protected-членам строже, чем в Java. Он позволяет обращаться к protected-членам только в подклассах класса, в котором определён член. В Java к членам, модифицированным ключевым словом protected, могут обращаться подклассы класса, определяющего член, а также другие классы в том же пакете.

Пример

package p {
    class Super {
        protected def f() {println("f")}
    }
    class Sub extends Super {
        f()
    }
    class Other {
        (new Super).f() // Ошибка
    }
}

В приведённом выше примере доступ класса Sub к f допустим, потому что f объявлен protected в Super, а Sub является подклассом Super. Напротив, доступ Other к f не разрешён, потому что Other не наследует от Super. Последнее также разрешено в Java, потому что Other и Sub находятся в одном пакете.


Публичные члены

В Scala, если модификатор не указан, по умолчанию используется public. К таким членам можно обращаться где угодно.

Пример

class Outer {
   class Inner {
      def f() { println("f") }
      class InnerMost {
         f() // Верно
      }
   }
   (new Inner).f() // Верно, потому что f() является общедоступным
}

Доступ package-private

Scala также поддерживает модификатор доступа package-private, который делает члены доступными только внутри конкретного пакета. Для этого после ключевого слова private указывается имя пакета. Формат таков:

private[x] 

или  

protected[x]

Здесьxозначает пакет, класс или singleton-объект, к которому он принадлежит.

Если записать какprivate[x], это читается так:"Этот член является приватным для всех остальных классов, кроме классов в […] или классов в пакете […] и их объектов-компаньонов."。

Этот приём очень полезен в больших проектах, охватывающих несколько пакетов. Он позволяет определять сущности, видимые в нескольких подпакетах вашего проекта, но остающиеся невидимыми для клиентов вне проекта.

Пример

package bobsrockets{
    package navigation{
        private[bobsrockets] class Navigator{
         protected[navigation] def useStarChart(){}
         class LegOfJourney{
             private[Navigator] val distance = 100
             }
            private[this] var speed = 200
            }
        }
        package launch{
        import navigation._
        object Vehicle{
        private[launch] val guide = new Navigator
        }
    }
}

В приведённом выше примере класс Navigator помечен как private[bobsrockets], что означает, что этот класс виден всем классам и объектам, содержащимся в пакете bobsrockets.

Например, доступ к Navigator из объекта Vehicle разрешён, потому что объект Vehicle содержится в пакете launch, а пакет launch находится в bobsrockets. И наоборот, любой код за пределами пакета bobsrockets не может получить доступ к классу Navigator.


Объекты-компаньоны и классы-компаньоны

В Scala объекты-компаньоны и классы-компаньоны могут получать доступ к приватным членам друг друга. Объект-компаньон и его класс-компаньон — это класс и объект с одинаковым именем в одном и том же файле.

Пример

class CompanionExample {
  private val privateField: String = "I am private in class"
}

object CompanionExample {
  def accessPrivateField(example: CompanionExample): String = {
    example.privateField  // Объект-компаньон может обращаться к приватным членам класса
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    val example = new CompanionExample
    println(CompanionExample.accessPrivateField(example))
  }
}
Другие расширения