Свойства классов #
Васильев Андрей Михайлович, 2024
Версии презентации
Объявление свойств #
Свойства в классах Kotlin могут быть объявлены либо как изменяемые (mutable) и неизменяемые (read-only) — var и val соответственно.
class Address {
var name: String = "Holmes, Sherlock"
var street: String = "Baker"
var city: String = "London"
var state: String? = null
var zip: String = "123456"
}
Для того чтобы воспользоваться свойством, просто обратитесь к нему по имени.
fun copyAddress(address: Address): Address {
val result = Address() // в Kotlin нет никакого слова `new`
result.name = address.name // вызов методов доступа
result.street = address.street
// ...
return result
}
Работа ключевого слова val #
Объявление поля с помощью ключевого слова val
class Sample(val name: String)
можно сравнить со следующим кодом на Java
public class Sample {
private String name;
public Sample(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Работа ключевого слова var #
Объявление поля с помощью ключевого слова var
class Counter(var value: Int)
можно сравнить со следующим кодом на Java
public class Counter {
private int value;
public Counter(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value
}
}
Только свойства в Kotlin можно использовать в левой части присваивания
Геттеры и сеттеры #
Полный синтаксис объявления свойства выглядит так:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
Инициализатор property_initializer
, геттер и сеттер можно не указывать. Также
необязательно указывать тип свойства, если он может быть выведен из
инициализатора или из возвращаемого типа геттера.
var initialized = 1 // имеет тип Int, стандартный геттер и сеттер
var allByDefault // ошибка: необходима явная инициализация,
// предусмотрены стандартные геттер и сеттер
Неизменяемые свойства #
Синтаксис объявления неизменяемых свойств имеет два отличия от синтаксиса объявления изменяемых свойств:
- объявление неизменяемого свойства начинается с ключевого слова
val
вместоvar
- объявление сеттера запрещено
val simple: Int? // имеет тип Int, стандартный геттер,
// должен быть инициализирован в конструкторе
val inferredType = 1 // имеет тип Int и стандартный геттер
Определение геттера #
Вы можете самостоятельно определить методы доступа для свойства
Если вы определяете пользовательский геттер, он будет вызываться каждый раз, когда вы обращаетесь к свойству (таким образом, вы можете реализовать вычисляемое свойство)
class Rectangle(val width: Int, val height: Int) {
val area: Int
get() = this.width * this.height // тип свойства необязателен, поскольку он может быть выведен из возвращаемого типа геттера
}
Вы можете опустить тип свойства, если его можно определить с помощью геттера.
val area get() = this.width * this.height
Определение сеттера #
Если вы определяете пользовательский сеттер, он будет вызываться каждый раз, когда вы присваиваете значение свойству, за исключением его инициализации.
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // парсит строку и устанавливает
// значения для других свойств
}
По договорённости, имя параметра сеттера - value
, но вы можете использовать
любое другое.
Теневые поля #
В Kotlin поле используется только как часть свойства для хранения его значения в
памяти. Поля не могут быть объявлены напрямую. Однако, когда свойству требуется
теневое поле (backing field), Kotlin предоставляет его автоматически. На это
теневое поле можно обратиться в методах доступа, используя идентификатор field
:
var counter = 0 // инициализатор назначает резервное поле напрямую
set(value) {
if (value >= 0)
field = value // значение при инициализации записывается
// прямиком в backing field
}
Идентификатор field может быть использован только в методах доступа к свойству.
Теневое поле будет сгенерировано для свойства, если оно использует стандартную
реализацию как минимум одного из методов доступа, либо если пользовательский
метод доступа ссылается на него через идентификатор field