Getters et Setters à Kotlin

86

En Java, par exemple, je peux écrire des getters moi-même (générés par IDE) ou utiliser des annotations comme @Getter dans lombok - ce qui était assez simple.

Kotlin a cependant des getters et des setters par défaut . Mais je ne comprends pas comment les utiliser.

Je veux le faire, disons - similaire à Java:

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

Alors, comment fonctionnent les getters?

nutella_eater
la source

Réponses:

142

Les getters et les setters sont générés automatiquement dans Kotlin. Si vous écrivez:

val isEmpty: Boolean

Il est égal au code Java suivant:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

Dans votre cas, le modificateur d'accès privé est redondant - isEmpty est privé par défaut et n'est accessible que par un getter. Lorsque vous essayez d'obtenir la propriété isEmpty de votre objet, vous appelez la méthode get en réel. Pour plus de compréhension des getters / setters dans Kotlin: les deux exemples de code ci-dessous sont égaux:

var someProperty: String = "defaultValue"

et

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

Je tiens également à souligner que thisdans un getter n'est pas votre propriété - c'est l'instance de classe. Si vous souhaitez accéder à la valeur du champ dans un getter ou un setter, vous pouvez utiliser le mot réservé fieldpour cela:

val isEmpty: Boolean
  get() = field

Si vous souhaitez uniquement avoir une méthode get en accès public, vous pouvez écrire ce code:

var isEmpty: Boolean
    private set 

en raison du modificateur privé près de l'accesseur set, vous ne pouvez définir cette valeur que dans les méthodes de votre objet.

Cortwave
la source
16
In your case the private access modifier is redundantComment? Le modificateur par défaut de Kotlin doc est public. kotlinlang.org/docs/reference/visibility-modifiers.html
@Rien oui, cela ressemble à un champ public, mais sous le capot, vous appelez la méthode getter
Cortwave
Le val isEmpty: Booleanne sera pas compilé car isEmpty n'est pas encore initialisé, non? Je commence juste à apprendre Kotlin. Aussi, que se passe- get() = fieldt-il?
Shubham A.
1
@Chiara val's have no setter
chroder
@chroder oui vous avez raison, j'ai dû mal lire ... commentaire supprimé. Merci de l'avoir signalé
Chiara
30

Les règles relatives aux modificateurs de visibilité des accesseurs de propriété sont les suivantes:

  • La visibilité Getter de varet de la valpropriété doit être exactement la même que la visibilité de la propriété, vous ne pouvez donc dupliquer explicitement que le modificateur de propriété, mais il est redondant:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • La visibilité de la varpropriété par le poseur doit être la même ou moins permissive que la visibilité de la propriété:

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

Dans Kotlin, les propriétés sont toujours accessibles via getter et setter, il n'est donc pas nécessaire de créer une propriété privateavec des publicaccesseurs comme en Java - son champ de sauvegarde (s'il est présent) est déjà privé. Ainsi, les modificateurs de visibilité sur les accesseurs de propriété ne sont utilisés que pour rendre la visibilité du setter moins permissive:

  • Pour une propriété avec un champ de sauvegarde et des accesseurs par défaut:

    var x = 0 // `public` by default
        private set
    
  • Pour une propriété sans champ de support:

    var x: Int // `public` by default
        get() = 0
        protected set(value: Int) { }
    
touche de raccourci
la source
Peut-on définir et obtenir différents types? Réglage x égal à certains "Some String"et retour, disons la longueur,, 11de la chaîne?
Carel
@Carel, non, pour l'instant, ce cas d'utilisation n'est pas pris en charge: les accesseurs d'une propriété doivent fonctionner avec exactement le type de la propriété. L'utilisation d'un type différent est couverte par l'utilisation d'une propriété de sauvegarde distincte
raccourci clavier
Merde, Kotlin est si proche de Python que vous pensez que cela fonctionnera simplement lorsque vous vous rappellerez qu'il est tapé ... et que vous vous coupez la gorge.
Carel
Merci pour les modificateurs d'accès. J'ai supprimé privated'une variable, et il est devenu accessible à partir d'une autre classe avec getter.
CoolMind
J'obtiens un "Les setters privés ne sont pas autorisés pour les propriétés ouvertes" lorsque j'utilise la combinaison "var x // private set". Résolu en déclarant comme "final var x"
Tom
14

1) Exemple par défaut setteret getterpour la propriété firstName dans Kotlin

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

}

En utilisant

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

SI votre setterou getterest exactement le même ci-dessus, vous pouvez le supprimer car il n'est pas nécessaire

2) Exemple de setter et getter personnalisés.

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

En utilisant

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

Plus
je commence à apprendre Kotlin à partir de Java, donc je suis confus fieldet propertyparce qu'en Java il n'y en a pas property.
Après quelques recherches, je vois fieldet propertydans Kotlin ressemble à C # ( Quelle est la différence entre un champ et une propriété? )

Voici quelques articles pertinents qui parlent de fieldet propertyen Java et Kotlin.
java a-t-il quelque chose de similaire aux propriétés C #?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Corrigez-moi si je me trompe. J'espère que ça aide

Phan Van Linh
la source
Merci, ça m'aide vraiment!
marcode_ely
8

Getter dans kotlin est par défaut public, mais vous pouvez définir le setter sur private et définir la valeur en utilisant une méthode à l'intérieur d'une classe. Comme ça.

/**
* 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}")
}
Lalit Behera
la source
5

Vous pouvez voir ce tutoriel pour plus d'informations:

Encore un autre didacticiel Kotlin pour les développeurs Android

Propriétés

Dans le monde Kotlin, les classes ne peuvent pas avoir de champs, juste des propriétés. Le mot-clé var nous indique que la propriété est modifiable, contrairement à val. Voyons un exemple:

class Contact(var number: String) {

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

}

Il n'y a pas beaucoup de code, mais beaucoup de choses se passent dans les coulisses. Nous allons le parcourir étape par étape. Tout d'abord, nous avons créé un contact public de classe finale.

C'est la règle principale à laquelle nous devons faire face: si ce n'est pas spécifié autrement, les classes sont publiques et finales par défaut (au fait, il en va de même pour les méthodes de classe). Si vous souhaitez hériter de la classe, marquez-la avec un mot-clé ouvert.

Pluton65
la source
0

Voici un exemple pratique et réel d'un getter et d'un setter Kotlin (voir plus de détails ici ):

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

Ricky Padilla
la source