Kotlin'de Getters ve Setters


89

Örneğin Java'da, alıcıları kendi başıma yazabilirim (IDE tarafından oluşturulmuş) veya lombok'ta @ Getter gibi Ek Açıklamalar kullanabilirim - ki bu oldukça basitti.

Ancak Kotlin , varsayılan olarak alıcılara ve ayarlayıcılara sahiptir . Ama onları nasıl kullanacağımı anlayamıyorum.

Bunu yapmak istiyorum, diyelim - Java'ya benzer:

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

Peki alıcılar nasıl çalışır?

Yanıtlar:


148

Toplayıcılar ve ayarlayıcılar Kotlin'de otomatik olarak oluşturulur. Eğer yazarsan:

val isEmpty: Boolean

Aşağıdaki Java koduna eşittir:

private final Boolean isEmpty;

public Boolean isEmpty() {
    return isEmpty;
}

Sizin durumunuzda, özel erişim değiştirici fazlalıktır - isEmpty varsayılan olarak özeldir ve yalnızca bir alıcı tarafından erişilebilir. Nesnenizin isEmpty özelliğini almaya çalıştığınızda, gerçek olarak get yöntemini çağırırsınız. Kotlin'deki alıcıların / ayarlayıcıların daha iyi anlaşılması için: aşağıdaki iki kod örneği eşittir:

var someProperty: String = "defaultValue"

ve

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

Ayrıca this, bir alıcıdaki mülkünüzün değil, sınıf örneğinin bu olduğunu belirtmek isterim . Alıcı veya ayarlayıcıda alanın değerine erişmek istiyorsanız, fieldbunun için ayrılmış kelimeyi kullanabilirsiniz :

val isEmpty: Boolean
  get() = field

Yalnızca genel erişimde bir alma yöntemine sahip olmak istiyorsanız - bu kodu yazabilirsiniz:

var isEmpty: Boolean
    private set 

set erişimcisinin yakınındaki özel değiştirici nedeniyle bu değeri yalnızca nesnenizin içindeki yöntemlerde ayarlayabilirsiniz.


17
In your case the private access modifier is redundantNasıl? Kotlin belgesi, varsayılan değiştiricinin genel olduğunu söylüyor. kotlinlang.org/docs/reference/visibility-modifiers.html

@Hiçbir şey evet, kamuya açık alan gibi görünüyor, ancak başlık altında alıcı yöntemi diyorsunuz
Cortwave

val isEmpty: BooleanİsEmpty henüz başlatılmadı olarak, hakkını derlemek değil mi? Kotlin'i öğrenmeye yeni başlıyorum. Ayrıca, ne oluyor get() = field?
Shubham A.

1
@Chiara val's setter yok
chroder

@chroder evet haklısın, yanlış okumuş olmalıyım ... yorum silindi. Gösterdiğiniz için teşekkürler
Chiara

30

Özellik erişimcileri görünürlük değiştiricileriyle ilgili kurallar şunlardır:

  • Alıcı görünürlüğü varve valözelliği, mülkün görünürlüğüyle tamamen aynı olmalıdır , bu nedenle özellik değiştiriciyi yalnızca açıkça çoğaltabilirsiniz, ancak gereksizdir:

    protected val x: Int
        protected get() = 0 // No need in `protected` here.
    
  • varMülkün belirleyici görünürlüğü, mülkün görünürlüğüyle aynı veya daha az izin verici olmalıdır :

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

KOTLIN olarak, özellikler hep bu şekilde bir özellik yapımında gerek yoktur, alıcı ve ayarlayıcı aracılığıyla erişilen privateile publicJava gibi erişimcileri - onun arka alanını (varsa) zaten özeldir. Bu nedenle, mülk erişimcilerindeki görünürlük değiştiricileri yalnızca ayarlayıcı görünürlüğünü daha az izin verici hale getirmek için kullanılır:

  • Destek alanı ve varsayılan erişimcileri olan bir mülk için:

    var x = 0 // `public` by default
        private set
    
  • Destek alanı olmayan bir mülk için:

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

Biri ayarlayabilir ve farklı türler alabilir mi? x Bazılarına eşit ayarlama "Some String"ve geri dönme 11, dizenin uzunluğunu söyler mi?
Carel

@Carel, hayır, şu an itibariyle bu kullanım durumu desteklenmiyor: bir mülkün erişimcileri tam olarak mülkün türüyle çalışmalıdır. Farklı bir tür kullanmak, ayrı bir destek özelliği
kısayol tuşu

Kahretsin, Kotlin Python'a o kadar yakın ki, sadece yazıldığı hatırlatıldığında işe yarayacağını düşünüyorsun ... ve kendi boğazını kesti.
Carel

Erişim değiştiriciler için teşekkürler. privateBir değişkenden çıkardım ve alıcı ile başka bir sınıftan erişilebilir hale geldi.
CoolMind

"Var x // private set" kombinasyonunu kullanırken "Açık özellikler için özel ayarlayıcılara izin verilmiyor" mesajı alıyorum. "Son var x" olarak bildirilerek çözüldü
Tom

15

1) Örnek varsayılan setterve Kotlin'deki mülkgetter için firstName

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

}

Kullanma

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

EĞER sizin setterveya getterolduğu tam olarak aynı yukarıda o olduğu için bunu kaldırabilirsiniz gereksiz

2) Örnek özel ayarlayıcı ve alıcı.

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

Kullanma

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

Daha fazla
Java'dan Kotlin öğrenmeye başladım, bu yüzden kafamı karıştırıyorum fieldve propertyçünkü Java'da yok property.
Bazı aramadan sonra, görüyorum fieldve propertyC # gibi Kotlin görünüm içinde ( bir alan ve bir özellik arasındaki fark nedir? )

İşte Java ve Kotlin hakkında fieldve bunlardan bahseden bazı ilgili yazı property.
Java'nın C # özelliklerine benzer bir özelliği var mı?
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531

Eğer Yanlışsam beni düzelt. Umarım yardımcı olur


Teşekkür ederim, gerçekten bana yardımcı oluyor!
marcode_ely

8

Kotlin'deki alıcı varsayılan olarak geneldir, ancak ayarlayıcıyı özel olarak ayarlayabilir ve bir sınıf içinde bir yöntem kullanarak değeri ayarlayabilirsiniz. Bunun gibi.

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

Daha fazla bilgi için bu eğiticiye bakabilirsiniz:

Android Geliştiricileri için Yine Başka Bir Kotlin Eğitimi

Özellikleri

Kotlin dünyasında, sınıfların alanları olamaz, sadece özellikleri vardır. var anahtar sözcüğü bize val'in aksine özelliğin değiştirilebilir olduğunu söyler. Bir örnek görelim:

class Contact(var number: String) {

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

}

Çok fazla kod yok ama perde arkasında pek çok şey oluyor. Bunu adım adım inceleyeceğiz. Her şeyden önce, genel bir final sınıfı Contact oluşturduk.

Bu, yüzleşmemiz gereken birincil kuraldır: aksi belirtilmedikçe, sınıflar geneldir ve varsayılan olarak nihaidir (bu arada, aynı şey sınıf yöntemleri için de geçerlidir). Sınıftan miras almak istiyorsanız, onu open anahtar sözcüğüyle işaretleyin.


0

İşte bir Kotlin alıcı ve ayarlayıcının pratik, gerçek dünyadan bir örneği (Daha fazla ayrıntıya buradan bakın ):

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.