Kesenjangan dimenangkan. Menerjemahkan dokumentasi Konvensi Koding Kotlin dari JetBrains

Halo, Habr! Saya membawa perhatian Anda pada terjemahan penulis dari halaman dokumentasi Konvensi Coding Kotlin dari JetBrains.


Dokumentasi asli


Konten:



Menggunakan panduan Gaya di Intellij Idea


Untuk menerapkan pemformatan di Intellij Idea sesuai dengan manual saat ini, Anda perlu menginstal plugin Kotlin versi 1.2.20 atau lebih baru, buka Pengaturan | Editor | Gaya Kode | Kotlin, klik tautan "Set dari ..." di sudut kanan atas dan pilih "Gaya standar" / Panduan gaya Kotlin "dari menu tarik-turun.


Untuk memverifikasi bahwa kode Anda diformat sesuai dengan gaya yang disarankan, buka pengaturan inspeksi dan aktifkan centang "Kotlin | Gaya masalah | File tidak diformat sesuai dengan pengaturan proyek". Aturan validasi lainnya, seperti konvensi penamaan, diaktifkan secara default.


Struktur proyek


Struktur folder


Dalam proyek menggunakan bahasa yang berbeda, file dengan kode Kotlin harus terletak di folder yang sama dengan kode dalam bahasa lain dan menggunakan struktur file yang sama yang diterima untuk bahasa utama. Misalnya, untuk Java, file harus terletak di struktur folder sesuai dengan nama paket.


Dalam proyek yang hanya menggunakan Kotlin, struktur folder yang disarankan adalah: gunakan folder untuk mengatur paket dengan direktori root dilewati, mis. jika semua kode dalam proyek berada dalam paket "org.example.kotlin" dan paket-paketnya, maka file sumber yang termasuk dalam paket "org.example.kotlin" harus berada di direktori root proyek, dan file dengan kode sumber paket "org. example.kotlin.foo.bar "harus terletak di subdirektori" foo / bar "relatif terhadap root proyek.


Nama file sumber


Jika file Kotlin hanya berisi satu kelas (mungkin terkait dengan deklarasi tingkat atas), maka itu harus dinamai, serta kelas dengan ekstensi .kt . Jika file berisi beberapa kelas atau hanya memiliki deklarasi tingkat atas, pilih nama yang menjelaskan isi file tersebut dan beri nama file yang sesuai. Gunakan punuk unta dengan huruf besar pertama untuk memberi nama file (mis. ProcessDeclarations.kt ).


Nama file harus menjelaskan apa yang dilakukan kode dalam file tersebut. Artinya, Anda harus menghindari kata-kata yang tidak berarti seperti "Util" untuk menamai file.


Mengatur file sumber


Menempatkan beberapa deklarasi (kelas, fungsi atau properti tingkat atas) dalam file sumber Kotlin yang sama diterima jika deklarasi ini terkait erat satu sama lain secara semantik dan ukuran file tetap masuk akal (tidak lebih dari beberapa ratus baris).


Secara khusus, ketika mendefinisikan fungsi ekstensi untuk kelas yang berlaku untuk semua aspek penerapan kelas ini, letakkan mereka di file yang sama di mana kelas itu sendiri didefinisikan. Ketika mendefinisikan fungsi ekstensi yang bermakna hanya untuk konteks spesifik menggunakan kelas ini, tempatkan di sebelah kode yang menggunakan fungsi ekstensi. Jangan membuat file hanya untuk menyimpan "semua ekstensi Foo."


Struktur kelas


Biasanya, konten kelas diurutkan dalam urutan berikut:


  • Deklarasi Properti dan Blok Inisialisasi
  • Konstruktor Sekunder
  • Deklarasi Metode
  • Objek Pendamping

Jangan mengurutkan deklarasi metode secara alfabet atau visual, dan jangan pisahkan metode biasa dari metode ekstensi. Sebagai gantinya, kumpulkan kode yang terhubung secara logis sehingga seseorang yang membaca kelas dari atas ke bawah dapat mengikuti logika apa yang terjadi. Pilih satu urutan pengurutan (kode tingkat lebih tinggi terlebih dahulu [barang tingkat tinggi dulu] dan detailnya nanti atau sebaliknya) dan patuhi itu.


Tempatkan kelas bersarang di sebelah kode yang menggunakan kelas ini. Jika kelas dimaksudkan untuk penggunaan eksternal dan tidak dirujuk dalam kelas, letakkan di akhir setelah objek pendamping.


Kerangka Implementasi Antarmuka


Saat mengimplementasikan antarmuka, pertahankan struktur yang sama dengan antarmuka yang sedang dilaksanakan (jika perlu, gantilah dengan metode pribadi tambahan yang digunakan untuk implementasi)


Struktur yang Digantikan


Redefinisi selalu disatukan, satu demi satu.


Aturan Penamaan


Kotlin mengikuti konvensi penamaan yang sama seperti Jawa. Khususnya:


Nama paket huruf kecil dan jangan gunakan garis bawah (org.example.myproject). Menggunakan nama banyak kata pada umumnya tidak disarankan, tetapi jika Anda perlu menggunakan beberapa kata, Anda bisa menggabungkannya atau menggunakan punuk unta (org.examle.myProject).


Nama kapital dan objek dimulai dengan huruf kapital dan menggunakan punuk unta:


 open class DeclarationProcessor { ... } object EmptyDeclarationProcessor : DeclarationProcessor() { ... } 

Nama Fungsi


Nama fungsi, properti, dan variabel lokal dimulai dengan huruf kecil dan tidak mengandung garis bawah:


 fun processDeclarations() { ... } var declarationCount = ... 

Pengecualian: fungsi pabrik yang digunakan untuk membuat instance kelas mungkin memiliki nama yang sama dengan kelas yang dibuat:


 abstract class Foo { ... } class FooImpl : Foo { ... } fun Foo(): Foo { return FooImpl(...) } 

Nama metode pengujian


Dalam pengujian (dan hanya dalam pengujian) diizinkan untuk menggunakan nama metode dengan spasi yang terlampir dalam koma terbalik. (Perhatikan bahwa nama metode seperti itu saat ini tidak didukung oleh runtime Android.) Garis bawah dalam nama metode juga diperbolehkan dalam kode pengujian.


 class MyTestCase { @Test fun `ensure everything works`() { ... } @Test fun ensureEverythingWorks_onAndroid() { ... } } 

Penamaan Properti


Nama konstan (properti berlabel const , atau properti tingkat atas atau objek val tanpa fungsi get kustom yang berisi data tidak dapat diubah) harus dikapitalisasi, dipisahkan oleh garis bawah:


 const val MAX_COUNT = 8 val USER_NAME_FIELD = "UserName" 

Nama tingkat atas atau properti objek yang berisi objek dengan perilaku atau data yang bisa berubah harus menggunakan nama umum dalam punuk unta:


 val mutableCollection: MutableSet<String> = HashSet() 

Nama properti yang mereferensikan objek Singleton dapat menggunakan gaya penamaan yang sama dengan deklarasi kelas:


 val PersonComparator: Comparator<Person> = ... 

Untuk penghitungan, Anda dapat menggunakan nama yang ditulis dalam huruf kapital yang dipisahkan oleh garis bawah atau gaya punuk unta, dimulai dengan huruf kapital, tergantung penggunaan.


 enum class Color { RED, GREEN } 

 enum class Color { RedColor, GreenColor } 

Catatan Penerjemah: Hanya saja jangan mencampur gaya yang berbeda. Pilih satu gaya dan pertahankan sesuai desain Anda.


Menamai Properti Tersembunyi


Jika kelas memiliki dua properti yang secara konseptual sama, tetapi satu adalah bagian dari API publik dan yang lainnya adalah bagian dari implementasi, gunakan garis bawah sebagai awalan untuk nama properti tersembunyi:


 class C { private val _elementList = mutableListOf<Element>() val elementList: List<Element> get() = _elementList } 

Memilih Nama yang Tepat


Nama kelas biasanya kata benda atau frasa yang menjelaskan apa kelasnya:


 List, PersonReader 

Nama metode biasanya merupakan kata kerja atau tindakan frase yang menjelaskan apa yang dilakukan metode:


 close, readPersons 

Nama juga harus menunjukkan apakah metode mengubah objek atau mengembalikan yang baru. Misalnya, sort adalah sort yang mengubah koleksi, dan sorted adalah kembalinya salinan koleksi yang baru disortir.


Nama harus dengan jelas menunjukkan tujuan entitas, jadi lebih baik untuk menghindari penggunaan kata-kata yang tidak berarti ( Manager , Wrapper , dll.) Dalam nama.


Saat menggunakan akronim sebagai bagian dari nama iklan, gunakan huruf kapital jika terdiri dari dua huruf ( IOStream ); atau hanya huruf besar, jika lebih panjang ( XmlFormatter , HttpInputStream ).


Memformat


Dalam kebanyakan kasus, Kotlin mengikuti konvensi pemformatan Java.


Gunakan 4 spasi untuk indentasi. Jangan gunakan tab.


Untuk kawat gigi, letakkan penahan pembuka di ujung garis di mana struktur dimulai dan penopang penutup pada garis yang terpisah, sejajar secara horizontal dengan struktur bukaan.


 if (elements != null) { for (element in elements) { // ... } } 

(Catatan: di Kotlin, titik koma adalah opsional, jadi pembungkus garis itu penting. Desain bahasa melibatkan kurung kurawal dalam gaya Java, dan Anda mungkin menemukan perilaku eksekusi kode yang tidak terduga jika Anda mencoba menggunakan gaya pemformatan yang berbeda.)


Ruang horisontal


Tempatkan spasi di sekitar operator biner (a + b) . Pengecualian: jangan letakkan spasi di sekitar operator "range to" (0..i)


Jangan letakkan spasi di sekitar operator unary (a++)


Tempatkan spasi di antara kata-kata kontrol kunci ( if , when , for dan while ) dan tanda kurung pembuka yang sesuai.


Jangan meletakkan spasi di depan braket pembuka di deklarasi utama konstruktor, metode, atau metode.


 class A(val x: Int) fun foo(x: Int) { ... } fun bar() { foo(1) } 

Jangan pernah beri spasi setelah ( , [ atau sebelum ] , ) .


Jangan pernah menempatkan ruang di sekitar titik . atau operator ?. :


 foo.bar().filter { it > 2 }.joinToString() foo?.() 

Beri spasi setelah slash ganda untuk komentar // :


 //   

Jangan letakkan spasi di sekitar kurung sudut yang digunakan untuk menunjukkan parameter tipe:


 Class Map<K, V> { ... } 

Jangan letakkan spasi di sekitar titik dua untuk menunjukkan referensi ke metode :: class:


 Foo::class String::length 

Jangan menaruh spasi sebelumnya ? digunakan untuk menandai null :


 String? 

Secara umum, hindari segala jenis perataan horisontal. Mengganti nama pengidentifikasi dengan nama dengan panjang yang berbeda tidak akan memengaruhi pemformatan kode.


Usus besar


Beri spasi sebelum titik dua : dalam kasus berikut:


  • ketika digunakan untuk memisahkan tipe dari tipe super;

 abstract class Foo<out T : Any> 

  • ketika mendelegasikan ke konstruktor superclass atau konstruktor lain dari kelas yang sama;

 constructor(x: String) : super(x) { ... } constructor(x: String) : this(x) { ... } 

  • setelah objek kata kunci.

 val x = object : IFoo { ... } 

Jangan beri spasi sebelumnya : saat memisahkan iklan dan tipenya.


 abstract fun foo(a: Int): T 

Selalu beri spasi setelah :


 abstract class Foo<out T : Any> : IFoo { abstract fun foo(a: Int): T } class FooImpl : Foo() { constructor(x: String) : this(x) { ... } val x = object : IFoo { ... } } 

Pemformatan Deklarasi Kelas


Kelas dengan beberapa parameter konstruktor dasar dan nama pendek dapat ditulis pada satu baris:


 class Person(id: Int, name: String) 

Kelas dengan nama yang lebih panjang atau jumlah parameter harus diformat sehingga setiap parameter utama konstruktor berada pada baris terpisah dengan lekukan. Selain itu, braket penutup harus berada di jalur baru. Jika kita menggunakan warisan, maka panggilan ke konstruktor dari superclass atau daftar antarmuka yang diimplementasikan harus terletak pada baris yang sama dengan braket:


 class Person( id: Int, name: String, surname: String ) : Human(id, name) { ... } 

Saat menentukan antarmuka dan memanggil konstruktor superclass, konstruktor superclass pertama-tama harus ditemukan, kemudian nama antarmuka pada baris baru dibenarkan-kiri:


 class Person( id: Int, name: String, surname: String ) : Human(id, name), KotlinMaker { ... } 

Untuk kelas dengan daftar panjang tipe super, Anda perlu memberi garis istirahat setelah titik dua dan menyelaraskan semua nama tipe super secara horizontal ke kiri:


 class MyFavouriteVeryLongClassHolder : MyLongHolder<MyFavouriteVeryLongClass>(), SomeOtherInterface, AndAnotherOne { fun foo() { ... } } 

Untuk memisahkan dengan jelas tajuk kelas dan tubuhnya ketika tajuk kelas panjang, baik tempatkan baris kosong setelah tajuk kelas (seperti dalam contoh di atas), atau tempatkan brace pembuka pada garis yang terpisah:


 class MyFavouriteVeryLongClassHolder : MyLongHolder<MyFavouriteVeryLongClass>(), SomeOtherInterface, AndAnotherOne { fun foo() { ... } } 

Gunakan indentasi biasa (4 spasi) untuk parameter konstruktor.


Dasar Pemikiran: ini memastikan bahwa properti yang dideklarasikan di konstruktor utama memiliki indentasi yang sama dengan properti yang dideklarasikan di tubuh kelas.


Pengubah


Jika iklan berisi beberapa pengubah, selalu atur dalam urutan berikut:


 public / protected / private / internal expect / actual final / open / abstract / sealed / const external override lateinit tailrec vararg suspend inner enum / annotation companion inline infix operator data 

Tempatkan semua anotasi sebelum pengubah:


 @Named("Foo") private val foo: Foo 

Jika Anda tidak bekerja di perpustakaan, abaikan pengubah yang berlebihan (mis. Publik).


Format anotasi


Anotasi biasanya ditempatkan pada baris terpisah sebelum deklarasi yang dilampirkan, dan dengan indentasi yang sama:


 @Target(AnnotationTarget.PROPERTY) annotation class JsonExclude 

Anotasi tanpa argumen dapat ditemukan di satu baris:


 @JsonExclude @JvmField var x: String 

Satu anotasi tanpa argumen dapat ditempatkan pada baris yang sama dengan deklarasi yang sesuai:


 @Test fun foo() { ... } 

Anotasi file


Anotasi ke file ditempatkan setelah komentar pada file (jika ada), sebelum pernyataan paket dan dipisahkan dari paket oleh baris kosong (untuk menekankan fakta bahwa mereka ditujukan pada file, bukan paket).


 /** License, copyright and whatever */ @file:JvmName("FooBar") package foo.bar 

Pemformatan fungsi


Jika metode tanda tangan tidak cocok pada satu baris, gunakan sintaks berikut:


 fun longMethodName( argument: ArgumentType = defaultValue, argument2: AnotherArgumentType ): ReturnType { // body } 

Gunakan indentasi biasa (4 spasi) untuk parameter fungsi.


Dasar Pemikiran: konsistensi dengan parameter konstruktor

Lebih disukai menggunakan ekspresi tanpa kurung kurawal untuk fungsi yang terdiri dari satu baris.


 fun foo(): Int { // bad return 1 } fun foo() = 1 // good 

Pemformatan ekspresi satu baris


Jika isi fungsi baris tunggal tidak cocok pada baris yang sama dengan deklarasi, tuliskan tanda = di baris pertama. Lekuk tubuh ekspresi dengan 4 spasi.


 fun f(x: String) = x.length 

Pemformatan Properti


Untuk properti hanya baca yang sederhana, lebih baik menggunakan pemformatan baris tunggal:


 val isEmpty: Boolean get() = size == 0 

Untuk properti yang lebih kompleks, selalu gunakan get dan set pada baris yang berbeda:


 val foo: String get() { ... } 

Untuk properti dengan inisialisasi, jika initializer terlalu panjang, tambahkan jeda baris setelah tanda sama dengan dan indentasi empat spasi untuk string inisialisasi:


 private val defaultCharset: Charset? = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file) 

Memformat instruksi kontrol


Jika kondisi dalam pernyataan kontrol if atau when multi-line, selalu gunakan kurung kurawal di sekitar badan pernyataan. Indentasi setiap baris berikutnya dari kondisi dengan 4 spasi relatif terhadap awal pernyataan. Letakkan kurung penutup kondisi bersama dengan kurung kurawal pembukaan pada baris yang terpisah:


 if (!component.isSyncing && !hasAnyKotlinRuntimeInScope(module) ) { return createKotlinNotConfiguredPanel(module) } 

Pembenaran: perataan yang rapi dan pemisahan kondisi tubuh yang jelas dan kondisi tubuh

Tempatkan yang else , catch , finally kata kunci, serta kata kunci while dari loop do / while pada baris yang sama dengan braket keriting penutupan sebelumnya:


 if (condition) { // body } else { // else part } try { // body } finally { // cleanup } 

Jika kondisi saat instruksi terdiri dari beberapa blok, disarankan untuk memisahkan mereka dari satu sama lain dengan garis kosong:


 private fun parsePropertyValue(propName: String, token: Token) { when (token) { is Token.ValueToken -> callback.visitValue(propName, token.value) Token.LBRACE -> { // ... } } } 

Tempatkan blok pendek when pernyataan pada baris yang sama tanpa kurung kurawal.


 when (foo) { true -> bar() // good false -> { baz() } // bad } 

Memformat Panggilan Metode


Saat menggunakan daftar parameter yang panjang, tempatkan baris setelah tanda kurung. Letakkan 4 spasi dan kelompokkan argumen yang secara logis terkait pada satu baris.


 drawSquare( x = 10, y = 10, width = 100, height = 100, fill = true ) 

Gunakan spasi di sekitar tanda sama antara nama parameter dan nilainya.


Memformat Panggilan Fungsi Rantai


Saat menggunakan panggilan berantai, lakukan . atau ?. operator pada saluran baru dengan satu lekukan dalam 4 spasi:


 val anchor = owner ?.firstChild!! .siblings(forward = true) .dropWhile { it is PsiComment || it is PsiWhiteSpace } 

Panggilan pertama dalam rantai biasanya harus memiliki satu baris di depannya, tetapi itu normal untuk tidak membuatnya jika kode lebih baik dibaca dan masuk akal.


Memformat ekspresi lambda


Dalam ekspresi lambda, spasi harus digunakan di sekitar kurung kurawal dan di sekitar panah yang memisahkan parameter dari tubuh. Jika suatu panggilan menerima karakter lambda tunggal, itu harus digunakan di luar tanda kurung jika memungkinkan.


 list.filter { it > 10 } 

Saat menetapkan label ke ekspresi lambda, jangan beri spasi antara label dan kurung pembuka:


 fun foo() { ints.forEach lit@{ // ... } } 

Ketika mendeklarasikan nama parameter dalam ekspresi lambda multi-baris, letakkan nama pada baris pertama, lalu panah, dan pada baris baru, awal dari badan fungsi:


 appendCommaSeparated(properties) { prop -> val propertyValue = prop.get(obj) // ... } 

Jika daftar parameter tidak cocok pada satu baris, letakkan panah pada baris yang berbeda:


 foo { context: Context, environment: Env -> context.configureEnv(environment) } 

Dokumen


Saat menggunakan dokumentasi multi-baris, letakkan /** di baris terpisah, dan mulai setiap baris berikutnya dengan tanda bintang:


 /** * This is a documentation comment * on multiple lines. */ 

Dokumentasi singkat dapat ditempatkan pada satu baris:


 /** This is a short documentation comment. */ 

Secara umum, hindari menggunakan param dan kembalikan tag. Sebagai gantinya, sertakan deskripsi parameter dan kembalikan nilai langsung dalam komentar dokumentasi dan tambahkan referensi parameter di mana pun mereka disebutkan. Gunakan param dan kembali hanya ketika deskripsi panjang diperlukan yang tidak sesuai dengan makna teks utama.


 // Avoid doing this: /** * Returns the absolute value of the given number. * @param number The number to return the absolute value for. * @return The absolute value. */ fun abs(number: Int) = ... // Do this instead: /** * Returns the absolute value of the given [number]. */ fun abs(number: Int) = ... 

Menghindari Konstruksi yang Tidak Perlu


Banyak konstruksi sintaksis di Kotlin adalah opsional dan disorot oleh lingkungan pengembangan sebagai tidak perlu, Anda tidak boleh menggunakannya dalam kode Anda hanya untuk membuat kode Anda "jelas".


Gunakan Unit kata kunci


Dalam fungsi, penggunaan kata kunci Unit tidak boleh digunakan:


 fun foo() { // ": Unit" is omitted here } 

Titik koma


Hindari menggunakan tanda titik koma di setiap kesempatan.


Pola string


Jangan gunakan kurung kurawal saat memasukkan variabel sederhana ke string template. Gunakan kurung kurawal hanya untuk ekspresi panjang.


 println("$name has ${children.size} children") 

Penggunaan fitur bahasa secara idiomatis


Kekekalan


Lebih baik menggunakan data yang tidak bisa diubah sebelum data yang bisa diubah. Selalu mendeklarasikan variabel dan properti lokal sebagai val , bukan var , kecuali mereka benar-benar berubah.


Selalu gunakan antarmuka koleksi yang tidak dapat diubah ( Collection , List , Set , Map ) untuk mendeklarasikan koleksi yang tidak berubah. Pada setiap kesempatan, saat menggunakan metode pabrik untuk membuat koleksi, gunakan implementasi yang mengembalikan koleksi tidak berubah:


 // Bad: use of mutable collection type for value which will not be mutated fun validateValue(actualValue: String, allowedValues: HashSet<String>) { ... } // Good: immutable collection type used instead fun validateValue(actualValue: String, allowedValues: Set<String>) { ... } // Bad: arrayListOf() returns ArrayList<T>, which is a mutable collection type val allowedValues = arrayListOf("a", "b", "c") // Good: listOf() returns List<T> val allowedValues = listOf("a", "b", "c") 

: .



.


 // Bad fun foo() = foo("a") fun foo(a: String) { ... } // Good fun foo(a: String = "a") { ... } 

[Type alias]


, , :


 typealias MouseClickHandler = (Any, MouseEvent) -> Unit typealias PersonIndex = Map<String, Person> 

-


-, , it . - .


-


. - , . , - .


( @ ) .



, , boolean , .


 drawSquare(x = 10, y = 10, width = 100, height = 100, fill = true) 


try , if when , return :


 return if (x) foo() else bar() //   ,    if (x) return foo() else return bar() // return when(x) { 0 -> "zero" else -> "nonzero" } //   ,    when(x) { 0 -> return "zero" else -> return "nonzero" } 

if when


if when


 when (x) { null -> ... else -> ... } if (x == null) ... else ... //      

, when .


Boolean?


Boolean? , if (value == true) if (value == false) , if (value ?: false) if (value != null && value) .



filtet , map .. . : forEach ( for null forEach )


, , , .



until ( ):


 for (i in 0..n - 1) { ... } // bad for (i in 0 until n) { ... } // good 


.


\n escape- .


, trimIndent , , trimMargin , :


 assertEquals( """ Foo Bar """.trimIndent(), value ) val a = """if(a > 1) { | return a |}""".trimMargin() 


. , , .


:


  • ( )
  • ,


. , , , , . API, , . , .



infix , , . : and , to , zip . : add .


infix , .



, , . , , . , , .


 class Point(val x: Double, val y: Double) { companion object { fun fromPolar(angle: Double, radius: Double) = Point(...) } } 

, , .



: , , Kotlin null , null

public /, , Kotlin:


 fun apiCall(): String = MyJavaApi.getProperty("name") 

(package-level class-level) Kotlin:


 class Person { val name: String = MyJavaApi.getProperty("name") } 

, , Kotlin :


 fun main() { val name = MyJavaApi.getProperty("name") println(name) } 

apply / with / run / also / let


Kotlin . , :


  • ? , , it , this ( also let ). also , .

 // Context object is 'it' class Baz { var currentBar: Bar? val observable: Observable val foo = createBar().also { currentBar = it // Accessing property of Baz observable.registerCallback(it) // Passing context object as argument } } // Receiver not used in the block val foo = createBar().also { LOG.info("Bar created") } // Context object is 'this' class Baz { val foo: Bar = createBar().apply { color = RED // Accessing only properties of Bar text = "Foo" } } 

  • ? , apply also . , with , let run .

 // Return value is context object class Baz { val foo: Bar = createBar().apply { color = RED // Accessing only properties of Bar text = "Foo" } } // Return value is block result class Baz { val foo: Bar = createNetworkConnection().let { loadBar() } } 

  • null ? , apply , let run . , with also .

 // Context object is nullable person.email?.let { sendEmail(it) } // Context object is non-null and accessible directly with(person) { println("First name: $firstName, last name: $lastName") } 


API:


  • ( API)
  • ( )
  • KDoc public api, , /

Source: https://habr.com/ru/post/id431990/


All Articles