Getters e Setters a Kotlin


86

In Java, ad esempio, posso scrivere getter da solo (generato da IDE) o utilizzare annotazioni come @Getter in lombok, il che era piuttosto semplice.

Kotlin tuttavia ha getter e setter per impostazione predefinita . Ma non riesco a capire come usarli.

Voglio farlo, diciamo, simile a Java:

private val isEmpty: String
        get() = this.toString() //making this thing public rises an error: Getter visibility must be the same as property visibility.

Allora come funzionano i getter?

Risposte:


142

Getter e setter vengono generati automaticamente in Kotlin. Se scrivi:

val isEmpty: Boolean

È uguale al seguente codice Java:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

Nel tuo caso, il modificatore di accesso privato è ridondante: isEmpty è privato per impostazione predefinita ed è accessibile solo da un getter. Quando provi a ottenere la proprietà isEmpty del tuo oggetto, chiami il metodo get in real. Per una maggiore comprensione di getter / setter in Kotlin: i due esempi di codice seguenti sono uguali:

var someProperty: String = "defaultValue"

e

var someProperty: String = "defaultValue"
    get() = field
    set(value) { field = value }

Inoltre voglio sottolineare che thisin un getter non è tua proprietà, è l'istanza della classe. Se vuoi accedere al valore del campo in un getter o setter puoi usare la parola riservata fieldper esso:

val isEmpty: Boolean
  get() = field

Se vuoi solo avere un metodo get nell'accesso pubblico, puoi scrivere questo codice:

var isEmpty: Boolean
    private set 

a causa del modificatore privato vicino alla funzione di accesso set puoi impostare questo valore solo nei metodi all'interno del tuo oggetto.


16
In your case the private access modifier is redundantCome? Il modificatore predefinito del documento di Kotlin è pubblico. kotlinlang.org/docs/reference/visibility-modifiers.html

@Niente sì, sembra un campo pubblico, ma sotto il cofano si chiama metodo getter
Cortwave

Non val isEmpty: Booleanverrà compilato poiché isEmpty non è ancora inizializzato, giusto? Ho appena iniziato a imparare Kotlin. Inoltre, cosa sta succedendo get() = field?
Shubham A.

1
@Chiara val's have no setter
chroder

@chroder si hai ragione, devo aver letto male ... commento cancellato. Grazie per averlo segnalato
Chiara

30

Le regole sui modificatori di visibilità delle funzioni di accesso alle proprietà sono le seguenti:

  • La visibilità di vare la valproprietà dovrebbe essere esattamente la stessa della visibilità della proprietà, quindi puoi solo duplicare esplicitamente il modificatore di proprietà, ma è ridondante:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • La visibilità settoriale della varproprietà dovrebbe essere uguale o meno permissiva della visibilità della proprietà:

    protected var x: Int
        get() = 0
        private set(x: Int) { } // Only `private` and `protected` are allowed.
    

In Kotlin, le proprietà sono sempre accessibili tramite getter e setter, quindi non è necessario creare una proprietà privatecon publicfunzioni di accesso come in Java: il suo campo di supporto (se presente) è già privato. Quindi, i modificatori di visibilità sulle funzioni di accesso alle proprietà vengono utilizzati solo per rendere la visibilità del setter meno permissiva:

  • Per una proprietà con campo di supporto e funzioni di accesso predefinite:

    var x = 0 // `public` by default
        private set
    
  • Per una proprietà senza campo di supporto:

    var x: Int // `public` by default
        get() = 0
        protected set(value: Int) { }
    

Si può impostare e ottenere tipi diversi? Impostazione x uguale ad alcuni "Some String"e ritornando diciamo la lunghezza 11,, della stringa?
Carel

@Carel, no, per ora questo caso d'uso non è supportato: le funzioni di accesso di una proprietà dovrebbero funzionare esattamente con il tipo di proprietà. L'utilizzo di un tipo diverso è coperto dall'utilizzo di una proprietà di supporto separata
tasto di scelta rapida

Dannazione, Kotlin è così vicino a Python che pensi che funzionerà solo quando ti verrà ricordato che è stato digitato ... e ti tagli la gola.
Carel

Grazie per i modificatori di accesso. Ho rimosso privateda una variabile ed è diventato accessibile da un'altra classe con getter.
CoolMind

Ottengo un "Setter privati ​​non sono consentiti per le proprietà aperte" quando si utilizza la combinazione "var x // set privato". Risolto dichiarando "final var x"
Tom

14

1) Esempio predefinito settere getterper proprietà firstName in Kotlin

class Person {
    var firstName: String = ""
            get() = field       // field here ~ `this.firstName` in Java or normally `_firstName` is C#
            set(value) {
                field = value
            }

}

Utilizzando

val p = Person()
p.firstName = "A"  // access setter
println(p.firstName) // access getter (output:A)

SE il tuo settero getterè esattamente lo stesso sopra, puoi rimuoverlo perché non è necessario

2) Esempio di setter e getter personalizzati.

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

Utilizzando

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

Più
comincio a imparare Kotlin da Java quindi mi confondo fielde propertyperché in Java non c'è property.
Dopo qualche ricerca, vedo fielde propertyin Kotlin assomiglia a C # ( qual è la differenza tra un campo e una proprietà? )

Ecco alcuni post rilevanti che parlano di fielde propertyin Java e Kotlin.
java ha qualcosa di simile alle proprietà C #?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Correggimi se sbaglio. Spero che aiuti


Grazie, mi aiuta davvero!
marcode_ely

8

Getter in kotlin è di default pubblico, ma puoi impostare il setter su privato e impostare il valore utilizzando un metodo all'interno di una classe. Come questo.

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

Puoi vedere questo tutorial per maggiori informazioni:

Ancora un altro tutorial di Kotlin per sviluppatori Android

Proprietà

Nel mondo di Kotlin, le classi non possono avere campi, ma solo proprietà. La parola chiave var ci dice che la proprietà è mutabile, a differenza di val. Vediamo un esempio:

class Contact(var number: String) {

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

}

Non c'è molto codice, ma molte cose stanno accadendo dietro le quinte. Lo esamineremo passo dopo passo. Prima di tutto, abbiamo creato un contatto di classe finale pubblico.

Questa è la regola principale che dobbiamo affrontare: se non diversamente specificato, le classi sono pubbliche e finali per impostazione predefinita (a proposito, lo stesso vale per i metodi di classe). Se vuoi ereditare dalla classe, contrassegnalo con la parola chiave aperta.


0

Ecco un esempio pratico e reale di un getter e setter di Kotlin (vedi maggiori dettagli qui ):

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.