Геттеры и сеттеры в Котлине
Например, в 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"