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


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.