Перейти до вмісту

Освоюємо 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 — задає видимість в рамках компільованого модуля. Застосовується рідко.

Джерела

[ред.]