Освоюємо Kotlin/Модифікатори видимості
Модифікатори видимості (visibility modifiers) або ж модифікатори доступу (access modifiers) в Kotlin — це група ключових слів, що вказують на видимість елементів самого класу, його конструкторів властивостей, функцій та сеттерів властивостей (щодо геттерів, то вони мають ту ж видимість, що і сама властивість). В Kotlin це чотири ключові слова: public, private, protected та internal.
public
[ред.]По замовчуванню елементи мають публічну видимість(public), тому саме ключове слово public можна не вказувати.
class Person (var name:String){
var id:Int=0
fun introduce(){
println("Мене звати $name")
}
}
fun main(){
val person=Person("Володимир Неда") // доступне створення об'єкту
person.name // є доступ
person.id //є доступ
person.introduce() // є доступ
}
Як видно з функції main(), до усіх елементів об'єкту класу Person є доступ ззовні у функції main().
private
[ред.]Якщо застосувати private до класу. Тобто написати:
private class Person (var name:String){}
В такому разі створити об'єкт можна буде тільки в тому ж файлі, що знаходиться клас. Якщо ми у іншому файлі створимо функцію main() і в ній захочемо створити об'єкт типу Person, то компілятор нам видасть, що він не може отримати доступ до класу Person.
Якщо ж застосовувати модифікатор до елементів класу, то такі елементи будуть доступні лише в цьому класі:
private class Person (private var name:String){
private var id:Int=0
fun introduce(){
println("Мене звати $name") // всередині класу name доступне
}
}
fun main(){
val person=Person("Володимир Неда") // доступне створення об'єкту лише з цього ж файлу
person.name // нема доступу бо властвість private
person.id //нема доступу бо властивість private
person.introduce() // є доступ бо функція public
}
Вищенаведений код не буде компілюватись, бо доступу до властивостей name та id класу Person не буде. Компілятор видасть помилки. Те ж саме буде, якщо оголосити приватною функцію introduce().
Якщо ж застосовувати модифікатор до функції класу, то така функція буде доступна лише з інших функцій цього класу:
private fun introduce(){}
Ми не зможемо викликати її ззовні з функції main().
Модифікатор private дуже часто використовується для задання інкапсуляції - тобто закриття реалізації від доступу ззовні. Не завжди є доцільним задавати публічний доступ до властивостей та функцій. Часто до них роблять доступ лише через спеціальні відкриті функції, а все інше закривають.
Наприклад, дуже часто необхідно зробити попередню перевірку значення, перед присвоєнню властивістю. Тоді можемо оголосити сеттер властивості приватним. Для присвоєння використовується інша функція цього класу, яка здійснить перевірку і присвоїть значення.
open class Person (private var name:String){
var id:Int=0
private set //оголошуємо сеттер приватним
open fun setId(receivedId:Int){
//здійснюєм попередню перевірку отриманого значення
this.id = receivedId //присвоюємо id
}
}
fun main(){
val person =Person("Микола Недофед")
person.id=10// помилка!! немає доступу
person.setId(55) // лише так можемо присвоїти значення
println (person.id) // є доступ, лише set - private, get - open
}
Даний приклад є дещо надуманий і створений лише для демонстрації що сеттер може бути приватним. Cеттер сам по собі створений для того, щоб здійснювати перевірку. Тому краще б було написати бех всякого private:
var id:Int=0
set (value ){
//здійснюємо попередню перевірку
field=value //присвоюємо значення
}
Це особливість Kotlin, що для властивостей вже передбачені геттер та сеттери. Так у Java доступний лише підхід з окремими функціями для присвоєння значення поля.
Щодо класів нащадків, то для них також будуть недоступні приватні елементи класів.
protected
[ред.]Якщо ми хочемо відкрити доступ до елементів для класів нащадків, але зробити їх недоступними ззовні, то такі елементи слід оголосити protected:
open class Person (private var name:String){
protected var id:Int=0
open fun introduce(){
println("Мене звати $name") // всередині класу name доступне
}
}
class Doctor(name:String):Person(name){
override fun introduce() {
println (this.name) //помилка!!! властивість name - недоступна
println (this.id) // властивість id - доступна
}
}
internal
[ред.]internal — задає видимість в рамках компільованого модуля. Застосовується рідко.
Джерела
[ред.]