Kotlin Method (Sinf/Class)

Kotlinda statik usullar va sinflarni qanday yaratish mumkin

Kotlin va Javadagi obyektga yo'naltirilgan model o'rtasidagi asosiy farqlardan biri statik usullar va sinflarning ta'rifidir. Umuman olganda, statik sinfdan foydalanish uchun uni yaratish shart emas. Xuddi shunday, statik usulni chaqirish uchun biz faqat uning nomini bilishimiz kerak, bunday usul aniqlangan sinf ob'ektini yaratish uchun emas. Java-da sinflar statik maydonlar yoki usullarni osongina e'lon qilishi mumkin. Biroq, statik sinfning ta'rifi biroz murakkabroq. Boshqa tomondan, Kotlin paket darajasidagi funktsiyalar va hamroh kabi mahalliy konstruktsiyalar bilan ishni sezilarli darajada soddalashtiradi.

Kotlindagi statik sinflar

Java sifatida Kotlin bizga kodimizdagi ichki sinflarni aniqlash imkonini beradi. Biroq, Kotlinda ichki o'rnatilgan sinf sukut bo'yicha statikdir. Ya'ni, sukut bo'yicha Kotlindagi ichki o'rnatilgan sinflar qo'shuvchi sinfga havola qilmaydi:

lass Car(val model: String) {
    class Engine(val fuel: String)
}
fun main() {
    val engine = Car.Engine("Malibu")
    val car = Car("avtomobil modeli.")
    println(engine.fuel)
    println(car.model)
}

Yuqoridagi misolda biz sinf ichidagi ichki sinfni aniqladik. Ko'rib turganimizdek, biz alohida Car va Engine alohida misol keltira olamiz. Xususan, Engine obyektga havola bermasdan, car misolini yaratamiz. Ichkarida aniqlangan yagona ishora uning nomidir. Kotlindagi statik sinflar qo'shuvchi sinfning qo'shimcha obyektining xususiyatlariga kirishlari mumkin. Agar biz Kotlinda statik bo'lmagan ichki sinfni aniqlamoqchi bo'lsak, uni quyidagicha e'lon qilishimiz kerak:

class Car(val model: String) {
    inner class Engine(val fuel: String) {
        val forModel = this@Car.model
    }
}
fun main() {
    val engine = Car("avtomobil modeli.").Engine("Malibu")
    println("${engine.forModel} - ${engine.fuel}")
}

Endi bu Inner sifatida Engine belgilangan, biz Car misolini yaratishimiz va uni yaratish uchun Engine foydalanishimiz kerak. Ichkaridan Engine foydalanib, tashqi obyektga murojaat qilishimiz mumkin. Javaga o'xshab, ichki o'rnatilgan sinflarni ham qo'shuvchi sinf usuli doirasida e'lon qilish mumkin. Bunday holda, yangi sinf mahalliy tip bo'ladi. Kotlin yondashuvining asosiy afzalligi shundaki, u sukut bo'yicha xotira oqish xavfini cheklaydi. Javada ma'lum bir ichki o'rnatilgan sinf qo'shuvchi sinfga havolaga ega ekanligiga e'tibor bermaslik osonroq. Boshqa tomondan, Kotlinda bunday havola sukut bo'yicha mavjud emas. Ichki sinf yoki statik sinfdan foydalanish ko'p jihatdan bizning domenimizni modellashtirish usuliga bog'liq. Albatta, statik sinflar kodni ko'proq qayta ishlatish imkonini beradi, chunki biz bir-biriga yaqin bo'lgan (ehtimol) bog'liq komponentlarni aniqlashga imkon berib, qo'shuvchi sinfni yaratishga hojat yo'q.

Kotlindagi statik usullar

Kotlin statik usullar yoki o'zgaruvchilarni qanday aniqlashimiz mumkinligini sezilarli darajada soddalashtiradi. Xususan, u (hamroh) va paket darajasidagi funktsiyalardan foydalanadi.

Paket darajasidagi funktsiyalar

Kotlin faqat obyektga yo'naltirilgan til emas, chunki u funktsional dasturlash paradigmasini ham qo'llab-quvvatlaydi: paket darajasidagi funktsiyalar shu yerdan keladi. Nomidan ko'rinib turibdiki, ular ma'lum bir sinfga tegishli bo'lmagan, ammo paket ichida aniqlangan funktsiyalar (yoki a'zolar). Ko'pincha ular boshqa sinflardan mustaqil bo'lgan yordamchi funktsiyalardir. Masalan, biz ulardan sinfni ishga tushirish uchun qulay funksiyalarni amalga oshirish uchun foydalanishimiz mumkin. Dekart tekisligidagi nuqtani modellashtirish uchun bizda sinf mavjud deb faraz qilaylik:

package com.logrocket.blog
class Point(val x: Int, val y: Int) {
    override fun toString(): String = "Nuqta($x, $y)"
}        

Keyin, boshqa paketda biz quyidagi funktsiyalarni belgilashimiz mumkin:

// In file factory.kt
package com.logrocket.blog.utils
import com.logrocket.blog.Point
val centerPoint = Point(x = 0, y = 0)
fun onXAxis(x: Int) = Point(x, y = 0)
fun onYAxis(y: Int) = Point(x = 0, y)

Keyin yuqoridagi funksiya va qiymatlarni import qilish orqali ishlatishimiz mumkin:

package com.logrocket.blog
import com.logrocket.blog.utils.centerPoint
import com.logrocket.blog.utils.onXAxis
fun main() {
    val point = onXAxis(5)
    println(centerPoint)
    println(point)
}

Yuqoridagi asosiy funksiya va satrlarni chop etadi. Paketdagi ikkita paket darajasidagi funktsiyalarni qanday aniqlaganimizga e'tibor bering. Shuningdek, biz paket darajasidagi qiymatni aniqladik. Funktsiyalarga ham, qiymatga ham Javada qilganimizdek, hech qanday qo'shimcha sinflarga havolalarsiz kirish mumkin: biz ularni faqat import qilishimiz kerak. Paket darajasidagi funktsiyalar va qiymatlar Javadagi statik maydonlar va usullar uchun sintaktik shakardir. Kotlin kompilyatorining qiladigan ishi Kotlin fayli nomi bilan atalgan, unda statik usullar va maydonlarga ega Java sinfini yaratadi. Masalan, undagi funksiyalar nomli sinfga kompilyatsiya qilinadi (bu yerda sinf nomi fayl nomidan va PascalCaseda tuzilgan):

package com.logrocket.blog
import com.logrocket.blog.utils.centerPoint
import com.logrocket.blog.utils.onXAxis
fun main() {
    val point = onXAxis(5)
    println(centerPoint)
    println(point)
}    

Agar biz yaratilgan Java sinfining nomini o'zgartirmoqchi bo'lsak, @JvmName izohdan foydalanishimiz mumkin. Misol uchun, agar biz fabrika.kt ning boshiga izoh qo'ysak, hosil qilingan sinf o'rniga nomlanadi. Bunday izoh direktivdan oldin paydo bo'lishi kerak. Nihoyat, agar biz bir xil yaratilgan Java sinfiga ko'proq yordamchi funktsiyalarni kompilyatsiya qilishni xohlasak yoki bizda allaqachon nomli fayl mavjud bo'lsa, izohdan foydalanishimiz mumkin. Shunday qilib, kompilyator ko'rsatilgan nomga ega Java fasad sinfini va bir xil bo'lgan barcha Kotlin fayllaridan barcha deklaratsiyalarni yaratadi.

Obyektlar

Kotlinda e'lon qilish orqali biz singletonni, ya'ni faqat bitta misolga ega sinfni aniqlaymiz. Bunday misol dangasalik bilan, birinchi marta ishlatilganda, tarmoqdan xavfsiz tarzda yaratilgan. Masalan, biz yuqorida belgilagan funksiya va qiymatlarni guruhlash uchun quyidagilarni aniqlashimiz mumkin:

object PointFactory {
    val center = Point(x = 0, y = 0)
    fun onXAxis(x: Int) = Point(x, y = 0)
    fun onYAxis(y: Int) = Point(x = 0, y)
}         

Keyin, avvalgidan farqli o'laroq, biz uning funktsiyalariga kirish uchun nomini belgilashimiz kerak. Boshqacha qilib aytganda, qamrovni belgilaydi:

val point = PointFactory.onYAxis(5)

Har bir Kotlinning faqat bitta nusxasi bo'lgani uchun uning a'zolariga kirish uchun uning universial nomi object yetarli. Bu faqat statik usullar yoki o'zgaruvchilardan iborat Java sinfiga o'xshaydi, lekin biroz farq qiladi. Ikkinchi holda, biz Java sinfini xohlaganimizcha ko'p marta yaratishimiz mumkin (agar konstruktor bo'lmasa). Bunday holda, statik o'zgaruvchilar sinfning har bir misoli uchun bir xil bo'ladi. Boshqa tomondan, Kotlin bilan bizda faqat bitta misol bor.

Yordamchi obyektlar

Yuqoridagi misolda PointFactory u Point sinfga juda bog'langan, chunki u nuqtani yaratish uchun bir nechta usullarni o'z ichiga oladi. Bu kabi holatlarda biz uni hamroh qilishimiz mumkin:

class Point(val x: Int, val y: Int) {
    companion object {
            val center = Point(x = 0, y = 0)
            fun onXAxis(x: Int) = Point(x, y = 0)
            fun onYAxis(y: Int) = Point(x = 0, y)
    }
    override fun toString(): String = "Nuqta($x, $y)"
}

Companion yordamida biz usullarni e'lon qilishimiz va ularni misollar bilan emas, balki berilgan sinfga bog'lashimiz mumkin. Shunday qilib, biz sinf nomini ko'rsatish orqali funktsiyalarga murojaat qilishimiz mumkin:

val point = Point.onYAxis(5)

Xulosa

To'g'ri aytganda, sof obyektga yo'naltirilgan dasturlash tafakkurida hamma narsa sinf ichida yaxshiroq aniqlanadi. Biroq, yuqorida ko'rganimizdek, ko'pincha biz mavjud sinfga joylashtirish uchun turli xil usullarga muhtojmiz. Bu, masalan, sinfda ishlaydigan, lekin bu sinfning xatti-harakatlarini ifodalamaydigan yordamchi usullar bilan sodir bo'lishi mumkin. Java kabi tillarda ma'lum bir sinfda qamrovi boshqacha bo'lgan usullar bilan to'la sinflarni yoki sinflarni aniqlash odatiy holdir. Bu nazoratdan osongina chiqib ketadi va o'qish, saqlash va qayta ishlatish juda qiyin bo'lgan turli xil mas'uliyat va heterojen usullarga ega bo'lgan sinflarga olib keladi. Kotlin, o'z navbatida, faqat obyektga yo'naltirilgan til emas. U boshqa dasturlash paradigmalarini, masalan, funktsional paradigmalarni qo'llab-quvvatlaydi. Demak, u Java kabi obyekt yo'nalishini qat'iy qabul qilmaydi, bu bizga, masalan, hech qanday sinfga bog'liq bo'lmagan funktsiyalarni aniqlash imkonini beradi. Bir tomondan, bu kodning qayta ishlatilishini va barqarorligini yaxshilaydi. Bundan tashqari, biz kodlar bazamizning qaysi qismi berilgan funksiyadan foydalanishi mumkinligini tanlash uchun paket tuzilishi va ko'rinish kalit so'zlaridan foydalanishimiz mumkin. Yana ham yaxshisi, companion yordamida biz yordamchi dastur kodini u ishlaydigan sinfga imkon qadar yaqinroq aniqlashimiz mumkin. Boshqa tomondan, biz Kotlin yondashuvining erkinligi va moslashuvchanligiga e'tibor qaratishimiz kerak. Masalan, o'zgaruvchan to'plam darajasidagi o'zgaruvchini aniqlashga hech narsa to'sqinlik qilmaydi, bu juda zararli bo'lishi mumkin. Zamonaviy dasturlash tillarida bo'lgani kabi bizda bir xil narsani modellashtirish va bir xil natijaga erishishning bir qancha usullari mavjud. Demak, to'g'ri konstruktsiya nima ekanligini aniqlash va undan to'g'ri foydalanish har doim tajriba va sezgirlik masalasidir.