Kotlin Destek Alanı Ne İçin?


93

Bir Java geliştiricisi olarak, bir destek alanı kavramı bana biraz yabancı. Verilen:

class Sample {
    var counter = 0 // the initializer value is written directly to the backing field
    set(value) {
        if (value >= 0) field = value
    }
}

Bu destek alanı ne işe yarar? Kotlin belgeleri şunları söyledi:

Kotlin'deki sınıflarda alan olamaz. Bununla birlikte, bazen özel erişimcileri kullanırken bir destek alanına sahip olmak gerekir .

Neden? Ayarlayıcı içinde özellik adının kendisini kullanmanın farkı nedir, örneğin. *

class Sample {        
    var counter = 0
    set(value) {
        if (value >= 0) this.counter = value // or just counter = value?
    }
}

18
Özelliğin kendisini ayarlayıcıda kullanmak sonsuz bir özyineleme ile sonuçlanacaktır, çünkü özelliğe bir değer atamak her zaman ayarlayıcıyı çağıracaktır.
funglejunk

1
@Strelok benim hatam .... Kotlin'in this.counter = valuebelgelerini okurken Java eşdeğeri ile aynı olduğunu varsayıyordum .
Yudhistira Arya

5
Bu makale Alan vs Mülkiyet içindir.
avinash

Yanıtlar:


86

Çünkü, diyelim ki fieldanahtar kelimeniz yoksa, get()veya içindeki değeri gerçekten ayarlayamayacak / alamayacaksınız set(value). Özel erişimcilerdeki destek alanına erişmenizi sağlar.

Bu, örneğinizin eşdeğer Java kodudur:

class Sample {
    private int counter = 0;
    public void setCounter(int value) {
        if (value >= 0) setCounter(value);
    }
    public int getCounter() {
        return counter;
    }
}

Görünüşe göre bu iyi değil, çünkü ayarlayıcı sadece kendi içinde sonsuz bir yinelemedir, hiçbir şeyi değiştirmez. Kotlin'de her yazdığınızda foo.bar = value, a yerine bir ayarlayıcı çağrısına çevrileceğini unutmayın PUTFIELD.


DÜZENLEME: Java vardır alanları Kotlin sahipken özelliklerini alanlara göre daha ziyade üst düzey kavram olan.

İki tür özellik vardır: biri destek alanı olan, diğeri olmayan.

Destek alanı olan bir özellik, değeri bir alan biçiminde depolar. Bu alan, hafızada değer depolamayı mümkün kılar. Bu tür mülklere bir örnek, firstve secondözellikleridir Pair. Bu özellik, öğesinin bellek içi temsilini değiştirecektir Pair.

Destek alanı olmayan bir mülk, değerini doğrudan bellekte depolamaktan başka yollarla da saklamak zorunda kalacaktır. Diğer özelliklerden veya nesnenin kendisinden hesaplanmalıdır. Bu tür bir özelliğin bir örneği, bir alan tarafından desteklenmeyen, ancak özelliğe göre hesaplanan bir sonuç olan indicesuzantı özelliğidir. Böylece bellek içi gösterimini değiştirmeyecek (Java statik olarak yazılmış olduğu için bunu yapamaz).ListsizeList


Cevap için teşekkürler! Benim hatam ... Bunun this.counter = valuejava eşdeğeri ile aynı olduğunu varsayıyordum .
Yudhistira Arya

Belgelenen herhangi bir yer var mı? Teşekkürler :)
Alston


1
Bir sürü belirsiz açıklama. Neden a'nın fielddaha çok bir gösterici ya da mevcut bir üye değişkene başvuru gibi olduğunu açıkça söyleyemiyoruz . Yana get/sethemen followes counternedenle fieldanahtar kelime için bir referans counter. Sağ?
eigenfield

@typelogic bu yanıt, C / C ++ değil, Java / JS geçmişine sahip programcılar için en uygunudur (o zamanlar Kotlin / Native yoktur). Bulanık bulduğunuz şey, başkaları için ekmek ve tereyağıdır.
glee8e

32

Başlangıçta ben de bu kavramı anlamakta zorlandım. Öyleyse size bir örnek yardımıyla açıklamama izin verin.

Bu Kotlin sınıfını düşünün

class DummyClass {
    var size = 0;
    var isEmpty
        get() = size == 0
        set(value) {
            size = size * 2
        }
}

Şimdi koda baktığımızda, 2 özelliğe sahip olduğunu görebiliriz, yani - size(varsayılan erişimcilerle) ve isEmpty(özel erişimcilerle). Ama sadece 1 alanı var yani size. Sadece 1 alanı olduğunu anlamak için, bu sınıfın Java karşılığını görelim.

Araçlar -> Kotlin -> Kotlin ByteCode'u Android Studio'da Göster'e gidin. Decompile üzerine tıklayın.

   public final class DummyClass {
   private int size;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.size == 0;
   }

   public final void setEmpty(boolean value) {
      this.size *= 2;
   }
}

Açıkçası, java sınıfının yalnızca alıcı ve ayarlayıcı işlevlerine sahip olduğunu isEmptyve bunun için tanımlanmış bir alan olmadığını görebiliriz. Benzer şekilde Kotlin'de, isEmptymülk bu alana hiç bağlı olmadığından mülk için destek alanı yoktur . Böylece destek alanı yok.


Şimdi özel alıcı ve isEmptyözellik ayarlayıcısını kaldıralım .

class DummyClass {
    var size = 0;
    var isEmpty = false
}

Ve yukarıdaki sınıfın Java eşdeğeri

public final class DummyClass {
   private int size;
   private boolean isEmpty;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.isEmpty;
   }

   public final void setEmpty(boolean var1) {
      this.isEmpty = var1;
   }
}

Burada alanları hem görmek sizeve isEmpty. isEmptybir destek alanıdır çünkü isEmptymülk için alıcı ve ayarlayıcı buna bağlıdır.


4
İyi açıklama. Teşekkürler
Sonu Sanjeev

1
Gerçekten, açıklama için teşekkürler. Java'dan da Kotlin'e geldim ve mülk kavramı benim için yeni. Ama sizler ve rehberler sayesinde anladım. :)
Yamashiro Rion

Tanrı sizi kutsasın.
Andrea Cioccarelli

Bu cevabı beğendim, dürüstçe gerçeklere atıfta bulunuluyor. Hala şüpheliyim, çünkü C #field anahtar kelimeye ihtiyaç duymuyor , Kotlin'in dil iyileştirmesinin bu garip fieldanahtar kelimeyi kaldırması ve çaresiz ruhların sonsuz özyineleme uçurumuna düşmesini engellemesi mümkün müdür ?
eigenfield

9

Yedekleme alanları, doğrulama çalıştırmak veya durum değişikliğinde olayları tetiklemek için iyidir. Bir Java ayarlayıcıya / alıcısına kod eklediğiniz zamanları düşünün. Yedek alanlar benzer senaryolarda faydalı olacaktır. Ayarlayıcıları / alıcıları kontrol etmeniz veya bunlar üzerinde görünürlük sahibi olmanız gerektiğinde destek alanlarını kullanırsınız.

Alan adını alan adıyla atarken, aslında ayarlayıcıyı (yani set(value)) çağırırsınız . Sahip olduğunuz örnekte, this.counter = valuebiz yığınımızı aşana kadar set (değer) olarak yinelenir. Kullanımı fieldayarlayıcı (veya alıcı) kodunu atlar.


Üzgünüz, ancak açıklamanız açıklanması gereken terimi içeriyor. Ve sonra, önce bir Java senaryosundan alıntı yaptınız ve sonra aniden hiçbir uyarı yapmadan lains'i gerçek bir Kotlin ifadesine geçirdiniz. Anahtar kelime için Kotlin ihtiyacı C # dilinde fielddeğil, bu yüzden burada bahsettiğinizden daha iyi bir açıklamaya ihtiyacımız var.
eigenfield

2

Benim anlayış kullandığı alan içinde tesisin değerine bir referans olarak tanımlayıcı olsun ya kümesi değiştirmek veya tesisin değeri kullanmak istediğinizde, olsun veya sette .

Örneğin:

class A{
    var a:Int=1
        get(){return field * 2}    // Similiar to Java: public int geta(){return this.a * 2}
        set(value) {field = value + 1}
}

Sonra:

var t = A()
println(t.a)    // OUTPUT: 2, equal to Java code: println(t.a * 2)
t.a = 2         // The real action is similar to Java code: t.a = t.a +1
println(t.a)    // OUTPUT: 6, equal to Java code: println(t.a * 2)

0

Terminoloji backing fieldgizemle doludur. Kullanılan anahtar kelime field. get/setYöntemleri, hemen yanındaki hakkındadır üye değişkeni aşağıdaki olmaya olsun veya set bu kapı koruyucu yöntemler mekanizması yoluyla. fieldAnahtar kelime sadece edilecek üye değişkeni ifade eder ayarlamak veya almak . Mevcut KOTLIN kısmında, içeride doğrudan üye değişkeni başvuruda bulunamaz get ya set maalesef sonsuz özyinelemeye sonuçlanacaktır çünkü yeniden çağırmak-çünkü koruyucu kapak yöntemlerine get ya seti ve böylece derin uçuruma aşağı çalışma zamanını led.

In C # da, doğrudan alıcı / ayarlayıcı yöntemleri içinde üye değişkeni başvurabilir. Bu fieldanahtar kelimenin mevcut Kotlin'in onu nasıl uyguladığı fikrini sunmak için bu karşılaştırmaya atıfta bulunuyorum , ancak umarım sonraki sürümlerde kaldırılır ve sonsuz özyinelemeyle sonuçlanmadan üye değişkenine doğrudan referans vermemize izin verir.

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.