14-bo‘lim
Kengaytma funksiyalari
Mavjud turga o'z funksiyangizni qo'shish, kengaytma xossalari, nega ular statik bog'lanadi va operator hamda infiks shakllari.
Ushbu bo‘lim mundarijasi
Kengaytma - Kotlin ning eng o'ziga xos imkoniyatlaridan biri: mavjud turga o'z funksiyangizni qo'shish. Uning kodiga tegmasdan va merosga ham kirmasdan.
Birinchi kengaytma #
fun String.birinchiHarfKatta(): String =
if (isEmpty()) this else this[0].uppercase() + substring(1)
fun Int.kvadrat(): Int = this * this
fun main() {
println("malika".birinchiHarfKatta())
println("".birinchiHarfKatta())
println(7.kvadrat())
}
Malika
49
Shakli: fun Tur.nom(): Natija. Funksiya ichida this - chaqirilgan
obyekt (ko'pincha uni yozmasa ham bo'ladi).
Endi "matn".birinchiHarfKatta() deb yozish mumkin - go'yo bu
String ning o'z metodi.
Nima uchun kerak #
fun List<Int>.ortacha(): Double =
if (isEmpty()) 0.0 else sum().toDouble() / size
fun String.faqatRaqamlar(): String = filter { it.isDigit() }
fun Int.soatgaAylantir(): String = "%02d:%02d".format(this / 60, this % 60)
fun main() {
println(listOf(85, 92, 78).ortacha())
println(emptyList<Int>().ortacha())
println("+998 (90) 123-45-67".faqatRaqamlar())
println(145.soatgaAylantir())
}
85.0
0.0
998901234567
02:25
Uchala holatda ham biz o'zimiz yozmagan turlarga - List, String,
Int - foydali funksiya qo'shdik.
Ikkalasini solishtiring:
soatgaAylantir(ortacha(ballar.filter { it > 60 }))
ballar.filter { it > 60 }.ortacha().soatgaAylantir()
Ikkinchisi chapdan o'ngga, ish bajarilish tartibida o'qiladi. Birinchisida esa ichkaridan tashqariga qarab o'qish kerak.
Kotlin standart kutubxonasining katta qismi aynan shu sababdan kengaytma sifatida yozilgan.
Kengaytma xossalari #
val String.ikkinchiHarf: Char?
get() = if (length >= 2) this[1] else null
val <T> List<T>.ikkinchisi: T?
get() = if (size >= 2) this[1] else null
val Int.juftmi: Boolean
get() = this % 2 == 0
fun main() {
println("Kotlin".ikkinchiHarf)
println("K".ikkinchiHarf)
println(listOf(10, 20, 30).ikkinchisi)
println(4.juftmi)
println(7.juftmi)
}
o
null
20
true
false
Kengaytma xossasida saqlash joyi yo'q - shuning uchun u faqat
get() bilan yoziladi va har chaqirilganda hisoblanadi.
Kengaytmalar statik bog'lanadi #
Bu eng muhim tafsilot:
open class Hayvon
class It : Hayvon()
fun Hayvon.ovoz() = "noma'lum ovoz"
fun It.ovoz() = "Vov-vov!"
fun main() {
val it: It = It()
val hayvon: Hayvon = It()
println(it.ovoz())
println(hayvon.ovoz())
}
Vov-vov!
noma'lum ovoz
Ikkinchi natijaga diqqat qiling. hayvon o'zgaruvchisida It
obyekti turibdi, lekin Hayvon.ovoz() chaqirildi.
Sababi: kengaytmalar e'lon qilingan turga qarab tanlanadi, ichida nima turganiga emas. Ular sinfga qo'shilmaydi - kompilyator ularni oddiy funksiya chaqiruviga aylantiradi.
Ya'ni bu yerda polimorfizm ishlamaydi. Xatti-harakat turga qarab
o'zgarishi kerak bo'lsa - haqiqiy metod va override ishlating.
Kengaytma - qulaylik vositasi, vorislik o'rnini bosuvchi emas.
A'zo metod ustun keladi #
class Quti {
fun salom() = "a'zo metod"
}
fun Quti.salom() = "kengaytma"
fun main() {
println(Quti().salom())
}
a'zo metod
Agar sinfda shu nomli metod bo'lsa, u chaqiriladi. Kengaytma mavjud metodni "o'g'irlab" ololmaydi - bu xavfsizlik kafolati.
Null bo'lishi mumkin bo'lgan turga #
fun String?.xavfsizUzunlik(): Int = this?.length ?: 0
fun String?.boshMi(): Boolean = this == null || this.isBlank()
fun main() {
val bor: String? = "matn"
val yoq: String? = null
println(bor.xavfsizUzunlik())
println(yoq.xavfsizUzunlik())
println(yoq.boshMi())
println(" ".boshMi())
println("x".boshMi())
}
4
0
true
true
false
String? ga kengaytma yozsangiz, uni null ustida ham chaqirish
mumkin - ?. kerak emas. Standart kutubxonadagi isNullOrBlank()
aynan shunday ishlaydi.
Kengaytmaning ko'rinishi #
class Hisob(private val qoldiq: Int) {
fun ochiqQoldiq() = qoldiq
}
fun Hisob.yetarlimi(summa: Int): Boolean = ochiqQoldiq() >= summa
fun main() {
val h = Hisob(500000)
println(h.yetarlimi(200000))
println(h.yetarlimi(900000))
}
true
false
Yuqorida ochiqQoldiq() ishlatildi, chunki qoldiq xossasi
private.
Kengaytma sinfning tashqarisida turadi, shuning uchun u faqat ochiq a'zolarga kira oladi. Bu mantiqiy: aks holda inkapsulyatsiyani istalgan odam buzib qo'yardi.
infix #
infix fun Int.gacha(oxiri: Int): List<Int> = (this..oxiri).toList()
data class Nuqta(val x: Int, val y: Int)
infix fun Nuqta.qoshish(boshqa: Nuqta) = Nuqta(x + boshqa.x, y + boshqa.y)
fun main() {
println(1 gacha 5)
println(Nuqta(1, 2) qoshish Nuqta(3, 4))
println(1.gacha(5))
}
[1, 2, 3, 4, 5]
Nuqta(x=4, y=6)
[1, 2, 3, 4, 5]
infix - nuqtasiz va qavssiz yozish imkonini beradi. Shartlari:
bitta parametr, standart qiymat yo'q.
to ham aynan shunday funksiya - shuning uchun "a" to 1 deb
yozilardi.
Operatorlarni qayta yozish #
data class Pul(
val miqdor: Int,
val valyuta: String = "so'm"
) : Comparable<Pul> {
operator fun plus(boshqa: Pul) = Pul(miqdor + boshqa.miqdor, valyuta)
operator fun times(son: Int) = Pul(miqdor * son, valyuta)
override fun compareTo(other: Pul) = miqdor.compareTo(other.miqdor)
override fun toString() = "$miqdor $valyuta"
}
fun main() {
val a = Pul(50000)
val b = Pul(30000)
println(a + b)
println(a * 3)
println(a > b)
println(listOf(a, b).max())
}
80000 so'm
150000 so'm
true
50000 so'm
| Operator | Funksiya nomi |
|---|---|
+ | plus |
- | minus |
* | times |
/ | div |
[i] | get |
in | contains |
> < | compareTo |
operator fun compareTo ni shunchaki yozsangiz, > va < ishlaydi -
lekin max(), min() va sorted() ishlamaydi.
Sababi: bu funksiyalar turdan Comparable<T> interfeysini bajarishni
talab qiladi, faqat operator borligi yetarli emas.
Shuning uchun yuqoridagi misolda : Comparable<Pul> yozilgan va
compareTo override bilan belgilangan. Bu holatda operator
so'zini yozish shart emas - u interfeysdan meros bo'lib o'tadi.
Pul + Pul tabiiy o'qiladi. Lekin Talaba + Talaba nima degani?
Operatorni faqat ma'nosi aniq va bir xil tushuniladigan bo'lsa
qayta yozing. Shubhalansangiz - oddiy nomli metod yozing:
a.qoshish(b) hech kimni chalkashtirmaydi.
Qayerda e'lon qilish #
fun String.toza(): String = trim().lowercase()
class Hisobot {
fun Int.formatla(): String = "%,d".format(this)
fun chiqar(summa: Int) = "Summa: ${summa.formatla()}"
}
fun main() {
println(" SALOM ".toza())
println(Hisobot().chiqar(1500000))
}
salom
Summa: 1,500,000
Kengaytmani fayl darajasida (hamma joydan ko'rinadi) yoki sinf ichida (faqat o'sha sinfda) e'lon qilish mumkin.
StringgabirinchiHarfKatta()kengaytmasini yozing.Intgakub()kengaytmasini qo'shing.List<Int>gaortacha()yozing va bo'sh ro'yxatda sinang.- Kengaytma xossasi bilan
oxirgiHarfni qaytaring. - Ota va voris turlarga bir xil nomli kengaytma yozib, qaysi biri chaqirilishini tekshiring.
- Sinfdagi metod bilan bir xil nomli kengaytma yozing.
String?ga kengaytma yozib,nullustida chaqiring.infixfunksiya yozing.data classgaplusoperatorini qo'shing.- Telefon raqamidan faqat raqamlarni ajratuvchi kengaytma yozing.
Xulosa #
fun Tur.nom()- mavjud turga funksiya qo'shadi;this- chaqirilgan obyekt.- Kengaytma zanjirni chapdan o'ngga o'qishli qiladi.
- Kengaytma xossasida saqlash joyi yo'q - faqat
get(). - Kengaytmalar statik bog'lanadi: e'lon qilingan turga qarab tanlanadi, polimorfizm ishlamaydi.
- Sinfdagi a'zo metod ustun keladi.
Tur?ga kengaytmanullustida ham chaqiriladi.- Kengaytma yashirin a'zolarni ko'rmaydi.
infixnuqtasiz yozishga,operatoresa+kabi belgilarga imkon beradi - ikkalasini ham o'lchov bilan ishlating.
Keyingi bo'limda lambda va qamrov funksiyalarini ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.