Kotlin class and object properties and fields


Kotlin study Notes series tutorial

Kotlin Study Notes (1) – Overview, Learning Curve, Development Tools, Resources Kotlin Study Notes (2) – Basic Syntax Kotlin Study Notes (3) – Idioms Kotlin Study Notes (4) – Basic types of Kotlin Foundation Kotlin basics: Control flow, returns and jumps, packages and imports Kotlin basics: Classes and objects and inheritance


Properties and Fields

Declaration attributes

Kotlin’s classes can have attributes that can be declared mutable using the keyword var, otherwise using the read-only keyword val.

    class Kotlin3 {
        var name: String = "name"
        var age: Int = 5
        var city: String = "Beijing"
    }
Copy the code

To use an attribute, you simply refer to it by name, like a field in Java:

    fun copyKotlin3(kotlin3: Kotlin3):Kotlin3{
        val kotlin3 = Kotlin3()
        kotlin3.age = 30
        kotlin3.name = "kotlin4"
        return kotlin3
    }
Copy the code

Getters and Setters

The full syntax for declaring an attribute is

    var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]
Copy the code

Initializers, getters, and setters are optional. Attribute types can also be omitted if they can be inferred from the initializer (or from its getter return value, as shown below). Such as:

var defaultSize: Int? Var defaultTime = 1 // Type Int, default getter, and setterCopy the code

The syntax of a read-only property differs from that of a mutable property in two ways: 1) read-only properties start with val instead of var, and 2) read-only properties do not allow setters

val defaultSize: Int? // Error: default getter val defaultTime = 1Copy the code

We can customize accessors, much like normal functions, right inside property declarations. Here is an example of a custom getter:

    var defaultName: String 
        get() = this.toString()
        set(value) {
            value.toUpperCase()
        }
Copy the code

By convention, the name of the setter parameter is value, but you can choose another name if you like. Since Kotlin 1.1, the property type can be omitted if it can be inferred from the getter:

Var defaultAge get() = this.tostring () // omit String typeset(value) {
            value.toUpperCase()
        }  
Copy the code

If you need to change the visibility or annotation of an accessor, but do not need to change the default implementation, you can define accessors without defining their implementation:

    var changeAge: String = "aaa"
        private setThis setter is private and has a default implementation var changeName: String? = null @Injectset// Annotate this setter with InjectCopy the code

Behind the field

Fields cannot be declared directly in the Kotlin class. However, when a property requires a background field, Kotlin automatically provides it, and this background field can be referenced in the accessor using the field identifier:

    var count = 1
        set(value) {
            if (value > 0) field = value
        }
Copy the code

Field identifiers can only be used in accessors for attributes

If at least one accessor for a property uses the default implementation, or if a custom accessor references a background field through field, a background field will be generated for that property

For example, there is no behind the scenes field in the following case:

    val height: Int
    get() = defaultTime
Copy the code

Behind the properties

So if your requirements don’t fit into this “implicit backing Property” solution, you can always get a backing property:

    private var _table: Map<String, Int>? = null
    public val table: Map<String, Int>
        get() {
            if(_table == null) {_table = HashMap()return_table ? : throw AssertionError("Set to null by another thread")}Copy the code

In many ways, this is the same approach as Java. Because accessing private properties through default getters and setters is optimized, no function call overhead is introduced

Compile-time constant

Properties of known values can be marked as compile-time constants using the const modifier. These attributes need to satisfy the following conditions:

  • An idiom at the top level or of object
  • Class with a String or native value
  • There are no custom getters for these attributes to use in annotations:
    const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"

    @Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { …… }
    
Copy the code

Lazy initialization of properties and variables

In general, attributes declared as non-null types must be initialized in the constructor. However, this is often inconvenient. For example, a property can be initialized via dependency injection or in the setup method of a unit test, in which case you cannot provide a non-empty initializer inside the constructor, but you still want to avoid null-checking when referencing the property in the class body. To handle this, you can mark the property with the Lateinit modifier:

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {subject.method()}}Copy the code

This modifier can only be used for attributes in the class body (if the var attribute is declared in the main constructor, and only if the attribute has no custom getter or setter), and since Kotlin 1.2, also for top-level attributes and local variables. The property or variable must be of a non-null type and cannot be a primitive type.

Accessing an LateInit property before initialization throws a specific exception that explicitly identifies the fact that the property was accessed and that it was not initialized.

Check if a LateInit var is initialized (since 1.2)

To check if a lateinit var isInitialized, use.isinitialized on the reference to the attribute:

if (foo::bar.isInitialized) {
    println(foo.bar)
}
Copy the code

This detection is only available for lexically-accessible properties, that is, properties that are declared within the same type, within one of the peripheral types, or at the top of the same file.

Covering properties

See Kotlin Study Notes (6) – Kotlin classes and objects and inheriting —- override properties

Entrusted property

The most common type of attribute is simply read (and possibly written) from the background field. On the other hand, you can implement any behavior of a property using custom getters and setters. In between, there are some common patterns for how properties work, some examples: lazy values, read from maps by key values. Access the database. Notify listeners when they access, and so on.

These common behaviors can be implemented as libraries through delegate properties, which will be described in a future article


This article mainly introduces the attributes and fields of Kotlin classes and objects. The next article will study the interface of Kotlin


Personal blog: http://outofmemory.top/ CSDN address: http://blog.csdn.net/dazhaoDai making address: https://github.com/dazhaoDai