Геттеры и сеттеры в Котлине

Например, в 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.

Так как работают добытчики?

8 ответов

Решение

Геттеры и сеттеры генерируются автоматически в Котлине. Если вы напишите:

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 

благодаря модификатору private рядом с set accessor вы можете установить это значение только в методах внутри вашего объекта.

Правила для модификаторов видимости аксессоров свойств следующие:

  • Геттер видимость 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) { }
    

1) Пример по умолчанию setter а также getter для собственности firstName в Котлине

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 потому что в яве нет property,
После некоторого поиска я вижу field а также property в Kotlin выглядят как C# (В чем разница между полем и свойством?)

Вот некоторый соответствующий пост, о котором говорят field а также property на Яве и Котлине.
в java есть что-то похожее на свойства C#?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Поправь меня, если я ошибаюсь. Надеюсь, это поможет

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}")
}

Если у вас есть Var, вы можете:

      var property: String = "defVal"
              get() = field
              set(value) { field = value }

Но в случае Val вы не можете установить его однажды назначенный, поэтому не будет блока setter:

      val property: String = "defVal"
              get() = field

или если вам не нужен сеттер, тогда:

      val property: String = "defVal"
              private set

Вы можете увидеть этот учебник для получения дополнительной информации:

Еще одно учебное пособие по Kotlin для разработчиков Android

свойства

В мире Kotlin у классов не может быть полей, только свойства. Ключевое слово var сообщает нам, что свойство изменчиво, в отличие от val. Давайте посмотрим на пример:

class Contact(var number: String) {

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

}

Не так много кода, но многое происходит за кулисами. Мы пройдем это шаг за шагом. Прежде всего, мы создали общедоступный финальный класс Contact.

Это основное правило, с которым мы должны столкнуться: если не указано иное, классы являются общедоступными и финальными по умолчанию (кстати, то же самое относится и к методам классов). Если вы хотите наследовать от класса, пометьте его ключевым словом open.

Немного не согласен с главным ответом @Cortwave. Поля-члены Kotlinпо умолчанию являются окончательными, а не закрытыми . Вы должны написать частный модификатор , чтобы сделать его инкапсулированным внутри класса.

Ответ, который я искал здесь, заключается в том, автоматически ли kotlin генерирует геттеры и сеттеры для частных полей-членов или вам нужно делать это самостоятельно? Простая реализация в Android Studio показывает, что вам нужно написать ее самостоятельно.

Вот практический, реальный пример получателя и установщика Kotlin (подробнее см. Здесь):

// 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"

Другие вопросы по тегам