Геттери та сетери в Котліні


86

Наприклад, на Java я можу самостійно писати геттери (генеруються IDE) або використовувати Анотації на кшталт @Getter у lombok - що було досить просто.

Однак у Kotlin за замовчуванням є геттери та сеттери . Але я не можу зрозуміти, як ними користуватися.

Я хочу це зробити, скажімо - подібне до Java:

private val isEmpty: String
        get() = this.toString() //making this thing public rises an error: Getter visibility must be the same as property visibility.

То як працюють геттери?

Відповіді:


142

Геттери та сетери автоматично генеруються в Kotlin. Якщо ви пишете:

val isEmpty: Boolean

Він дорівнює такому коду Java:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

У вашому випадку модифікатор приватного доступу є зайвим - isEmpty є приватним за замовчуванням, і доступ до нього може отримати лише геттер. Коли ви намагаєтесь отримати властивість isEmpty свого об'єкта, ви викликаєте метод get у реальному. Для більш глибокого розуміння геттерів / сеттерів у Kotlin: два наведені нижче зразки коду рівні:

var someProperty: String = "defaultValue"

і

var someProperty: String = "defaultValue"
    get() = field
    set(value) { field = value }

Також я хочу зазначити, що thisв геттері - це не ваша властивість - це екземпляр класу. Якщо ви хочете отримати доступ до значення поля в геттері або сеттері, ви можете використовувати зарезервоване слово fieldдля цього:

val isEmpty: Boolean
  get() = field

Якщо ви хочете лише мати метод get у відкритому доступі - ви можете написати такий код:

var isEmpty: Boolean
    private set 

завдяки приватному модифікатору біля встановленого доступу ви можете встановити це значення лише в методах всередині вашого об'єкта.


16
In your case the private access modifier is redundantЯк Мовляв, за замовчуванням модифікатор документа Kotlin є загальнодоступним. kotlinlang.org/docs/reference/visibility-modifiers.html

@ Нічого так, здається, це загальнодоступне поле, але під капотом ви називаєте метод отримання
— Cortwave

val isEmpty: BooleanЧи не компілюватиметься IsEmpty ще не инициализирован, НЕ так? Тільки починаю вчити Котліна. Крім того, з чим це відбувається get() = field?
— Шубхем А.

1
У @Chiara valнемає
— сеттера

@chroder так, ти маєш рацію, я, мабуть, прочитав неправильно ... коментар видалено. Дякуємо, що вказали на це
— К'яра

30

Правила щодо модифікаторів видимості доступників властивостей є такими:

  • Отримані видимість varі valвластивість повинні бути абсолютно однаковими з видимістю властивості, таким чином, ви можете лише явно продублювати модифікатор властивості, але він є зайвим:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • Видимість об'єкта varнерухомості має бути такою ж або менш дозвільною, ніж видимість об'єкта

    protected var x: Int
        get() = 0
        private set(x: Int) { } // Only `private` and `protected` are allowed.
    

У Kotlin властивості завжди доступні через getter і setter, тому немає необхідності створювати властивість за privateдопомогою publicаксесуарів, як у Java - поле його підтримки (якщо воно є) вже є приватним. Отже, модифікатори видимості на засобах доступу до властивостей використовуються лише для того, щоб зробити видимість установника менш дозвільною:

  • Для властивості з полем резервного копіювання та стандартними засобами доступу:

    var x = 0 // `public` by default
        private set
    
  • Для власності без поля заповнення:

    var x: Int // `public` by default
        get() = 0
        protected set(value: Int) { }
    

Чи можна встановити та отримати різні типи? Встановлення x рівного деякому "Some String"та повернення, скажімо, довжини, 11рядка?
— Карел

@Carel, ні, наразі цей випадок використання не підтримується: користувачі ресурсу повинні працювати точно з типом властивості. Використання іншого типу охоплюється використанням окремої властивості підтримки
— гаряча клавіша

Боже, Котлін настільки близький до Python, що ти думаєш, що це спрацює, коли ти отримаєш нагадування, що його набрали ... і переріжеш собі горло.
— Карел

Дякуємо за модифікатори доступу. Я видалив privateзі змінної, і вона стала доступною для іншого класу з getter.
— CoolMind

Я отримую "Приватні установлювачі заборонені для відкритих властивостей" при використанні комбінації "var x // private set". Вирішено шляхом оголошення як "остаточний var x"
— Том,

14

1) Приклад за замовчуванням setterі getterдля власності firstName в Kotlin

class Person {
    var firstName: String = ""
            get() = field       // field here ~ `this.firstName` in Java or normally `_firstName` is C#
            set(value) {
                field = value
            }

}

Використовуючи

val p = Person()
p.firstName = "A"  // access setter
println(p.firstName) // access getter (output:A)

Якщо ваш setterабо getterце точно так же вище, ви можете видалити його , тому що це непотрібне

2) Приклади користувацького сеттера та геттера.

const val PREFIX = "[ABC]"

class Person {

    // set: if value set to first name have length < 1 => throw error else add prefix "ABC" to the name
    // get: if name is not empty -> trim for remove whitespace and add '.' else return default name
    var lastName: String = ""
        get() {
            if (!field.isEmpty()) {
                return field.trim() + "."
            }
            return field
        }
        set(value) {
            if (value.length > 1) {
                field = PREFIX + value
            } else {
                throw IllegalArgumentException("Last name too short")
            }
        }
}

Використовуючи

val p = Person()
p.lastName = "DE         " // input with many white space
println(p.lastName)  // output:[ABC]DE.
p.lastName = "D" // IllegalArgumentException since name length < 1

Більше
я починаю вивчати Kotlin з Java, тому я заплутаний fieldі propertyтому, що в Java немає property.
Після певного пошуку я бачу, fieldі propertyв Kotlin виглядає як C # ( Яка різниця між полем і властивістю? )

Ось декілька відповідних публікацій, які розповідають про fieldта propertyна Java та Kotlin.
чи має Java щось подібне до властивостей C #?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Виправте мене, якщо я помиляюся. Сподіваюся, це допоможе


Дякую, це мені справді допомогло!
— marcode_ely

8

Getter у kotlin за замовчуванням є загальнодоступним, але ви можете встановити сеттер як приватний і встановити значення за допомогою одного методу всередині класу. Подобається це.

/**
* Created by leo on 17/06/17.*/

package foo
class Person() {
var name: String = "defaultValue"
               private set

fun foo(bar: String) {
    name = bar // name can be set here
       }
}

fun main(args: Array<String>) {
  var p = Person()
  println("Name of the person is ${p.name}")
  p.foo("Jhon Doe")
  println("Name of the person is ${p.name}")
}

5

Ви можете переглянути цей підручник для отримання додаткової інформації:

Ще один підручник Kotlin для розробників Android

Властивості

У світі Котлін класи не можуть мати полів, а лише властивості. ключове слово var повідомляє нам, що властивість змінюється, на відміну від val. Подивимось приклад:

class Contact(var number: String) {

   var firstName: String? = null
   var lastName: String? = null
   private val hasPrefix : Boolean
       get() = number.startsWith("+")

}

Коду мало, але багато речей відбувається за лаштунками. Ми пройдемо це поетапно. Перш за все, ми створили публічний підсумковий клас Contact.

Це основне правило, з яким нам доводиться стикатися: якщо не вказано інше, класи за замовчуванням є загальнодоступними та остаточними (до речі, те саме стосується і методів класів). Якщо ви хочете успадкувати клас, позначте його ключовим словом open.


0

Ось практичний, реальний приклад геттера та сеттера Котліна (докладніше див. Тут ):

// Custom Getter
val friendlyDescription get(): String {
    val isNeighborhood = district != null
    var description = if (isNeighborhood) "Neighborhood" else "City"
    description += " in"
    if (isNeighborhood) {
        description += " $city,"
    }
    province?.let {
        if (it.isNotEmpty()) {
            description += " $it,"
        }
    }
    description += " $country"
    return description
}

print(myLocation.friendlyDescription) // "Neighborhood in Denver, Colorado, United States"


// Custom Setter
enum class SearchResultType {
    HISTORY, SAVED, BASIC
}

private lateinit var resultTypeString: String

var resultType: SearchResultType
    get() {
        return enumValueOf(resultTypeString)
    }
    set(value) {
        resultTypeString = value.toString()
    }

result.resultType = SearchResultType.HISTORY
print(result.resultTypeString) // "HISTORY"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.