Sebagai pengembang Java, konsep bidang pendukung agak asing bagi saya. Diberikan:
class Sample {
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
}
Apa gunanya backing field ini? Dokumen Kotlin mengatakan:
Kelas di Kotlin tidak boleh memiliki kolom. Namun, terkadang perlu memiliki backing field saat menggunakan aksesor kustom .
Mengapa? Apa bedanya dengan menggunakan nama properti itu sendiri di dalam penyetel, mis. *
class Sample {
var counter = 0
set(value) {
if (value >= 0) this.counter = value // or just counter = value?
}
}
android
kotlin
kotlin-android-extensions
Yudhistira Arya
sumber
sumber
this.counter = value
itu sama dengan Java yang setara ketika membaca dokumen Kotlin.Jawaban:
Karena, katakanlah jika Anda tidak memiliki
field
kata kunci, Anda tidak dapat benar-benar menyetel / mendapatkan nilai diget()
atauset(value)
. Ini memungkinkan Anda untuk mengakses bidang dukungan di pengakses khusus.Ini adalah kode Java yang setara dari sampel Anda:
class Sample { private int counter = 0; public void setCounter(int value) { if (value >= 0) setCounter(value); } public int getCounter() { return counter; } }
Rupanya ini tidak baik, karena penyetel hanyalah rekursi infinte ke dalam dirinya sendiri, tidak pernah mengubah apapun. Ingat di kotlin setiap kali Anda menulisnya,
foo.bar = value
itu akan diterjemahkan menjadi panggilan penyetel alih-alihPUTFIELD
.EDIT: Java memiliki kolom sementara Kotlin memiliki properti , yang merupakan konsep tingkat yang lebih tinggi daripada kolom.
Ada dua jenis properti: satu dengan bidang belakang, satu tanpa bidang.
Properti dengan backing field akan menyimpan nilai dalam bentuk field. Bidang itu memungkinkan penyimpanan nilai dalam memori. Contoh dari properti tersebut adalah properti
first
dansecond
propertiPair
. Properti itu akan mengubah representasi dalam memoriPair
.Properti tanpa backing field harus menyimpan nilainya dengan cara lain selain menyimpannya secara langsung di memori. Ini harus dihitung dari properti lain, atau, objek itu sendiri. Contoh dari properti tersebut adalah properti
indices
ekstensiList
, yang tidak didukung oleh bidang, tetapi hasil yang dihitung berdasarkansize
properti. Jadi itu tidak akan mengubah representasi dalam memoriList
(yang tidak dapat dilakukan sama sekali karena Java diketik secara statis).sumber
this.counter = value
itu sama dengan java setara.field
lebih seperti pointer atau referensi ke variabel anggota yang sudah ada. Karena ituget/set
segera mengikuticounter
,field
kata kunci adalah referensi kecounter
. Baik?Awalnya, saya juga kesulitan memahami konsep ini. Jadi izinkan saya menjelaskannya kepada Anda dengan bantuan sebuah contoh.
Pertimbangkan kelas Kotlin ini
class DummyClass { var size = 0; var isEmpty get() = size == 0 set(value) { size = size * 2 } }
Sekarang ketika kita melihat kode, kita dapat melihat bahwa ia memiliki 2 properti yaitu -
size
(dengan pengakses default) danisEmpty
(dengan pengakses kustom). Tetapi hanya memiliki 1 bidang yaitusize
. Untuk memahami bahwa ia hanya memiliki 1 kolom, mari kita lihat padanan Java untuk kelas ini.Pergi ke Tools -> Kotlin -> Show Kotlin ByteCode di Android Studio. Klik pada Dekompilasi.
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; } }
Jelas kita dapat melihat bahwa kelas java hanya memiliki fungsi pengambil dan penyetel
isEmpty
, dan tidak ada bidang yang dideklarasikan untuk itu. Demikian pula di Kotlin, tidak adaisEmpty
kolom backing untuk properti , karena properti tidak bergantung pada kolom itu sama sekali. Jadi tidak ada backing field.Sekarang mari kita hapus pengambil dan penyetel
isEmpty
properti kustom .class DummyClass { var size = 0; var isEmpty = false }
Dan padanan Java dari kelas di atas adalah
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; } }
Di sini kita melihat ladang
size
danisEmpty
.isEmpty
adalah bidang pendukung karena pengambil dan penyetel untukisEmpty
properti bergantung padanya.sumber
field
kata kunci, mungkinkah peningkatan bahasa Kotlin akan menghapusfield
kata kunci aneh ini dan menghindari jiwa yang tidak berdaya jatuh ke dalam jurang rekursi tak terbatas?Bidang pendukung baik untuk menjalankan validasi atau memicu peristiwa pada perubahan status. Pikirkan saat-saat Anda menambahkan kode ke penyetel / pengambil Java. Bidang pendukung akan berguna dalam skenario serupa. Anda akan menggunakan backing field saat Anda perlu mengontrol atau memiliki visibilitas atas setter / getter.
Saat menetapkan bidang dengan nama bidang itu sendiri, Anda sebenarnya memanggil penyetel (yaitu
set(value)
). Dalam contoh yang Anda miliki,this.counter = value
akan berulang menjadi set (nilai) sampai kami meluap tumpukan kami. Menggunakanfield
bypass kode penyetel (atau pengambil).sumber
field
tidak dalam C # jadi kami membutuhkan penjelasan yang lebih baik daripada yang Anda kutip di sini.Pemahaman saya adalah menggunakan field identifier sebagai referensi nilai properti di get atau set , ketika Anda ingin mengubah atau menggunakan nilai properti di get atau set .
Sebagai contoh:
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} }
Kemudian:
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)
sumber
Terminologi
backing field
itu penuh dengan misteri. Kata kunci yang digunakan adalahfield
. Theget/set
metode, berikut segera sebelah variabel anggota yang adalah tentang menjadi mendapatkan atau mengatur melalui pintu mekanisme metode pelindung ini. Thefield
kata kunci hanya mengacu pada variabel anggota yang akan mengatur atau mendapatkan . Saat ini Kotlin, Anda tidak dapat merujuk ke variabel anggota secara langsung di dalam get atau set metode pintu pelindung karena sayangnya akan menghasilkan rekursi tak terbatas karena itu akan memanggil kembali get atau set dan dengan demikian memimpin runtime ke jurang yang dalam.Dalam C # , Anda bisa langsung mereferensikan variabel anggota di dalam metode pengambil / penyetel. Saya mengutip perbandingan ini untuk menyajikan gagasan bahwa
field
kata kunci ini adalah bagaimana Kotlin saat ini mengimplementasikannya, tetapi saya berharap ini akan dihapus di versi selanjutnya dan memungkinkan kami untuk merujuk langsung variabel anggota secara langsung tanpa mengakibatkan rekursi tak terbatas.sumber