Pochodzące i setery w Kotlinie


86

Na przykład w Javie mogę samodzielnie pisać gettery (generowane przez IDE) lub używać adnotacji, takich jak @Getter w lombok - co było dość proste.

Kotlin ma jednak domyślnie metody pobierające i ustawiające . Ale nie rozumiem, jak ich używać.

Chcę to zrobić, powiedzmy - podobnie jak w Javie:

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

Jak więc działają gettery?

Odpowiedzi:


142

Metody pobierające i ustawiające są generowane automatycznie w Kotlinie. Jeśli napiszesz:

val isEmpty: Boolean

Odpowiada następującemu kodowi Java:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

W twoim przypadku modyfikator dostępu prywatnego jest zbędny - isEmpty jest domyślnie prywatny i może być dostępny tylko przez getter. Kiedy próbujesz uzyskać właściwość isEmpty obiektu, wywołujesz metodę get w rzeczywistości. Aby lepiej zrozumieć metody pobierające / ustawiające w Kotlinie: dwie poniższe próbki kodu są równe:

var someProperty: String = "defaultValue"

i

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

Chcę również zwrócić uwagę, że thisgetter nie jest twoją własnością - jest to instancja klasy. Jeśli chcesz uzyskać dostęp do wartości pola w getterze lub setterze, możesz użyć do tego zarezerwowanego słowa field:

val isEmpty: Boolean
  get() = field

Jeśli chcesz mieć tylko metodę get w dostępie publicznym - możesz napisać ten kod:

var isEmpty: Boolean
    private set 

ze względu na prywatny modyfikator w pobliżu metody dostępu set możesz ustawić tę wartość tylko w metodach wewnątrz obiektu.


16
In your case the private access modifier is redundantW jaki sposób? Doc Kotlin mówi, że domyślny modyfikator jest publiczny. kotlinlang.org/docs/reference/visibility-modifiers.html

@Nic, tak, wydaje się, że to pole publiczne, ale pod maską nazywasz metodę gettera
— Cortwave

val isEmpty: BooleanNie zostanie skompilowany jako isEmpty nie jest jeszcze zainicjowany, prawda? Dopiero zaczynam uczyć się Kotlina. Co się dzieje z get() = field?
— Shubham A.

1
@Chiara val's have no setter
— chroder

@chroder tak, masz rację, chyba źle przeczytałem ... komentarz został usunięty. Dzięki za zwrócenie uwagi
— Chiara

30

Zasady dotyczące modyfikatorów widoczności metod dostępu do właściwości są następujące:

  • Widoczność vari valwłaściwość pobierająca powinny być dokładnie takie same, jak widoczność właściwości, więc możesz tylko jawnie powielić modyfikator właściwości, ale jest to zbędne:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • Widoczność varwłaściwości ustawiająca powinna być taka sama lub mniej dopuszczalna niż widoczność właściwości:

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

W Kotlinie dostęp do właściwości jest zawsze uzyskiwany za pośrednictwem metody pobierającej i ustawiającej, dlatego nie ma potrzeby tworzenia właściwości privatez publicakcesoriami, takimi jak w Javie - jej pole zapasowe (jeśli jest obecne) jest już prywatne. Tak więc modyfikatory widoczności w akcesoriach właściwości są używane tylko po to, aby widoczność ustawiacza była mniej dopuszczalna:

  • W przypadku właściwości z polem zapasowym i domyślnymi metodami dostępu:

    var x = 0 // `public` by default
        private set
    
  • W przypadku właściwości bez pola zapasowego:

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

Czy można ustawić i uzyskać różne typy? Ustawienie x równe some "Some String"i zwrócenie, powiedzmy, długości 11ciągu?
— Carel

@Carel, nie, na razie ten przypadek użycia nie jest obsługiwany: metody dostępu do właściwości powinny działać dokładnie z typem właściwości. Używanie innego typu jest objęte oddzielną właściwością kopii zapasowej
— skrótem klawiszowym

Cholera, Kotlin jest tak bardzo bliski Pythonowi, że myślisz, że zadziała, gdy przypomnisz sobie, że został wpisany ... i poderżniesz sobie gardło.
— Carel

Dzięki za modyfikatory dostępu. Usunąłem privateze zmiennej i stał się dostępny z innej klasy za pomocą metody getter.
— CoolMind

Gdy używam kombinacji „var x // private set”, pojawia się komunikat „Private setters nie jest dozwolony dla otwartych właściwości”. Rozwiązany przez zadeklarowanie jako „ostateczna zmienna x”
— Tom,

14

1) Przykład domyślny setteri getterdla nieruchomości firstName w Kotlinie

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

}

Za pomocą

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

JEŚLI twój setterlub getterjest dokładnie taki sam powyżej, możesz go usunąć, ponieważ jest niepotrzebny

2) Przykład ustawiający i pobierający niestandardowy.

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

Za pomocą

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

Więcej
Zaczynam uczyć się Kotlina od Javy, więc jestem zagubiony fieldi propertyponieważ w Javie nie ma property.
Po jakimś wyszukiwaniu widzę fieldiw propertyKotlinie wyglądam jak C # ( Jaka jest różnica między polem a właściwością? )

Oto niektóre istotne stanowisko, które mówią o fieldi propertyw Java i Kotlin.
czy java ma coś podobnego do właściwości C #?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Popraw mnie, jeśli się mylę. Mam nadzieję, że to pomoże


Dziękuję, to naprawdę mi pomogło!
— marcode_ely

8

Metoda pobierania w kotlin jest domyślnie publiczna, ale można ustawić metodę ustawiającą na prywatną i ustawić wartość za pomocą jednej metody wewnątrz klasy. Lubię to.

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

Możesz zobaczyć ten samouczek, aby uzyskać więcej informacji:

Jeszcze jeden samouczek Kotlin dla programistów Androida

Nieruchomości

W świecie Kotlina klasy nie mogą mieć pól, tylko właściwości. Słowo kluczowe var mówi nam, że właściwość jest zmienna, w przeciwieństwie do val. Zobaczmy przykład:

class Contact(var number: String) {

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

}

Nie ma zbyt wiele kodu, ale za kulisami dzieje się wiele rzeczy. Przejdziemy przez to krok po kroku. Przede wszystkim stworzyliśmy ogólnodostępną klasę finałową Kontakt.

Jest to podstawowa zasada, z którą musimy się zmierzyć: jeśli nie określono inaczej, klasy są domyślnie publiczne i ostateczne (nawiasem mówiąc, to samo dotyczy metod klasowych). Jeśli chcesz dziedziczyć po klasie, zaznacz to słowem kluczowym open.


0

Oto praktyczny, rzeczywisty przykład metody pobierającej i ustawiającej Kotlin (zobacz więcej szczegółów tutaj ):

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.