Bu codelab'de, Programcılar için Kotlin Eğitim Programı kursunun bir parçası bulunmaktadır. Codelab'ler üzerinden sırayla çalışıyorsanız bu kurstan en iyi şekilde yararlanabilirsiniz. Bilginize bağlı olarak bazı bölümlere göz atabilirsiniz. Bu kurs, nesneye duyarlı bir dil bilen ve Kotlin öğrenmek isteyen programcılara yöneliktir.
Giriş
Bu codelab'de, Kotlin'de çiftler, koleksiyonlar ve uzantı işlevleri dahil olmak üzere çeşitli faydalı özellikler tanıtıyorsunuz.
Bu kurstaki dersler, tek bir örnek uygulama oluşturmak yerine bilginizi geliştirmek için tasarlanmıştır ancak birbirinizden yarı bağımsızdır. Böylece aşina olduğunuz bölümlere göz atabilirsiniz. Hepsini bir araya getirmek için, örneklerin çoğu akvaryum teması kullanır. Akvaryum hikayesinin tamamını görmek isterseniz Programcılar için Kotlin Eğitim Programı Udacity'deki kursa göz atabilirsiniz.
Bilmeniz gerekenler
- Kotlin işlevleri, sınıfları ve yöntemlerinin söz dizimi
- IntelliJ IDEA'da Kotlin's REPL (Read-Eval-Print Loop) ile çalışma
- IntelliJ IDEA'da yeni sınıf oluşturma ve program çalıştırma
Neler öğreneceksiniz?
- Çiftler ve üçlülerle çalışma
- Koleksiyonlar hakkında daha fazla bilgi
- Sabitleri tanımlama ve kullanma
- Uzantı işlevleri yazma
Yapacaklarınız
- REPL'deki çiftler, üçlüler ve karma haritalar hakkında bilgi edinin
- Sabit değerleri düzenlemenin farklı yollarını öğrenin
- Bir uzantı işlevi ve uzantı özelliği yazın
Bu görevde çiftleri ve üçlüleri öğrenip yıkma konusunda bilgi edinirsiniz. Çiftler ve üçlüler, 2 veya 3 genel öğe için önceden hazırlanmış veri sınıflarıdır. Bu, örneğin bir işlevin birden fazla değer döndürmesini sağlamak için yararlı olabilir.
Bir List
balıklarınız ve balığın tatlı su veya tuzlu su balığı olup olmadığını kontrol etmek için bir isFreshWater()
işlevine sahip olduğunuzu varsayalım. List.partition()
, biri koşulun true
, diğerinin koşulun false
olduğu öğelere sahip iki liste döndürür.
val twoLists = fish.partition { isFreshWater(it) }
println("freshwater: ${twoLists.first}")
println("saltwater: ${twoLists.second}")
1. Adım: Birkaç çift ve üçlü yapın
- REPL'i açın (Araçlar > Kotlin > Kotlin REPL).
- Kullanılan donanımla bir ekipman parçasını ilişkilendirerek bir çift oluşturun, ardından değerleri yazdırın. İki dize gibi iki değeri
to
anahtar kelimesiyle bağlayan bir ifade oluşturarak, ardından her bir değere başvuruda bulunmak için.first
veya.second
ifadesini kullanarak çift oluşturabilirsiniz.
val equipment = "fish net" to "catching fish"
println("${equipment.first} used for ${equipment.second}")
⇒ fish net used for catching fish
- Üçlü olarak oluşturup
toString()
ile yazdırın, ardındantoList()
ile bir listeye dönüştürün. Üç değer kullanarakTriple()
kullanarak üçlü oluşturursunuz. Her bir değeri ifade etmek için.first
,.second
ve.third
ifadelerini kullanın.
val numbers = Triple(6, 9, 42)
println(numbers.toString())
println(numbers.toList())
⇒ (6, 9, 42) [6, 9, 42]
Yukarıdaki örnekler, çiftin veya üçgenin tüm bölümleri için aynı türü kullanır ancak bu zorunlu değildir. Parçalar bir dize, bir sayı veya liste olabilir. Örneğin, başka bir çift veya üçlü.
- Çiftin ilk bölümünün çift olduğu bir çift oluşturun.
val equipment2 = ("fish net" to "catching fish") to "equipment"
println("${equipment2.first} is ${equipment2.second}\n")
println("${equipment2.first.second}")
⇒ (fish net, catching fish) is equipment ⇒ catching fish
2. Adım: Bazı çiftleri ve üçlüleri yok edin
Çiftleri ve üçlü parçaları parçalarına ayırmaya yıkma adı verilir. Çifti veya üç katına uygun sayıda değişken atayın. Kotlin her bir bölümün değerini sırayla atar.
- Çifti yok edin ve değerleri yazdırın.
val equipment = "fish net" to "catching fish"
val (tool, use) = equipment
println("$tool is used for $use")
⇒ fish net is used for catching fish
- Üçlü yıkım ve değerleri yazdırın.
val numbers = Triple(6, 9, 42)
val (n1, n2, n3) = numbers
println("$n1 $n2 $n3")
⇒ 6 9 42
Çiftler ve üçlülerin yok edilmesi, önceki bir codelab'de ele alınan veri sınıflarıyla aynı şekilde çalışır.
Bu görevde listeler ve yeni bir koleksiyon türü olan karma eşlemeler dahil olmak üzere koleksiyonlar hakkında daha fazla bilgi edinebilirsiniz.
1. Adım: Listeler hakkında daha fazla bilgi edinin
- Listeler ve yoksayılabilir listeler önceki bir derste kullanıma sunulmuştur. Bunlar, oldukça kullanışlı bir veri yapısı olduğundan Kotlin, listeler için çeşitli yerleşik işlevler sunar. Listeler için işlevlerin bu kısmi listesini inceleyin.
List
veMutableList
için Kotlin dokümanlarında tam girişler bulabilirsiniz.
İşlev | Amaç |
| Değiştirilebilir listeye öğe ekleyin. |
| Dönüştürülebilir listeden bir öğe kaldırın. |
| Öğelerin ters sırada listelendiği bir liste kopyasını döndürün. |
| Liste öğeyi içeriyorsa |
| Listenin ilk dizininden ikinci dizinine kadar olan kısmını tekrar ekleyin. |
- Hâlâ REPL üzerinde çalışıyorsa bir numara listesi oluşturun ve ona
sum()
çağrısı yapın. Bu işlem tüm öğeleri özetler.
val list = listOf(1, 5, 3, 4)
println(list.sum())
⇒ 13
- Dize listesi oluşturun ve listeyi toplayın.
val list2 = listOf("a", "bbb", "cc")
println(list2.sum())
⇒ error: none of the following functions can be called with the arguments supplied:
- Öğe,
List
öğesinin doğrudan nasıl toplanacağını bildiği bir şey (ör. bir dize) varsa lambda işleviyle.sumBy()
kullanarak bunun nasıl toplanacağını (örneğin, her dizenin uzunluğunun toplamına) belirtebilirsiniz. Bir lambda bağımsız değişkeni için varsayılan adit
'tir. Buradait
, listede gezinirken gerçekleştirilen her bir öğeyi ifade eder.
val list2 = listOf("a", "bbb", "cc")
println(list2.sumBy { it.length })
⇒ 6
- Listelerle yapabileceğiniz daha pek çok şey var. Kullanılabilir işlevselliği görmenin yollarından biri, IntelliJ IDEA'da bir liste oluşturmak, noktayı eklemek ve ardından ipucundaki otomatik tamamlama listesine bakmaktır. Bu, tüm nesneler için kullanılabilir. Bir listeyle deneyin.
- Listeden
listIterator()
seçin, ardından listedefor
ifadesiyle gezinin ve tüm öğeleri boşluklarla ayırarak yazdırın.
val list2 = listOf("a", "bbb", "cc")
for (s in list2.listIterator()) {
println("$s ")
}
⇒ a bbb cc
2. Adım: Karma eşlemelerini deneyin
Kotlin'de hashMapOf()
özelliğini kullanarak neredeyse her şeyi eşleyebilirsiniz. Karma haritalar, ilk değerin anahtar görevi gördüğü bir çift listesi gibidir.
- Balıkların belirtileri, anahtarları ve hastalıkları ve değerleriyle eşleşen bir karma haritası oluşturun.
val cures = hashMapOf("white spots" to "Ich", "red sores" to "hole disease")
- Ardından,
get()
veya hatta daha kısa, köşeli parantez[]
kullanarak belirti anahtarına göre hastalık değerini alabilirsiniz.
println(cures.get("white spots"))
⇒ Ich
println(cures["red sores"])
⇒ hole disease
- Haritada olmayan bir belirti belirtmeyi deneyin.
println(cures["scale loss"])
⇒ null
Haritada bir anahtar yoksa eşleşen hastalığa dönüş yapmaya çalışmak null
döndürür. Harita verilerine bağlı olarak, olası bir anahtarla eşleşmemek yaygın bir durumdur. Böyle durumlarda Kotlin, getOrDefault()
işlevini sağlar.
- Eşleşmeyen bir anahtarı
getOrDefault()
kullanarak aramayı deneyin.
println(cures.getOrDefault("bloating", "sorry, I don't know"))
⇒ sorry, I don't know
Kotlin, bir değer döndürmekten fazlasını yapmanız gerekiyorsa getOrElse()
işlevini sağlar.
- Kodunuzu
getOrDefault()
yerinegetOrElse()
kullanacak şekilde değiştirin.
println(cures.getOrElse("bloating") {"No cure for this"})
⇒ No cure for this
Basit bir varsayılan değer döndürmek yerine, süslü ayraçlar arasındaki kod {}
. Örnekte, else
bir dize döndürür, ancak tedavisi olan bir web sayfasını bulup döndürmek kadar eğlenceli olabilir.
mutableListOf
gibi, mutableMapOf
da yapabilirsiniz. Değişebilir harita, öğeleri koymanıza ve kaldırmanıza olanak sağlar. Değişmezlik, yalnızca değiştirilebildiği, değişmediği anlamına gelir.
- Bir ekipman dizesini öğe sayısıyla eşleyerek değiştirilebilen bir envanter haritası oluşturun. İçindeki balık ağlarıyla oluşturun, ardından
put()
ile envantere 3 tank çöpü ekleyin veremove()
ile balık ağını kaldırın.
val inventory = mutableMapOf("fish net" to 1)
inventory.put("tank scrubber", 3)
println(inventory.toString())
inventory.remove("fish net")
println(inventory.toString())
⇒ {fish net=1, tank scrubber=3}{tank scrubber=3}
Bu görevde Kotlin'deki sabit değerler ve bunları düzenlemenin farklı yöntemleri hakkında bilgi edineceksiniz.
1. Adım: Kontrast ve val hakkında bilgi edinin
- REPL'de sayısal bir sabit değer oluşturmayı deneyin. Kotlin'de
const val
düzeyinde üst düzey sabitler oluşturup derleme zamanında bir değer atayabilirsiniz.
const val rocks = 3
Değer atanır ve değiştirilemez. Bu, normal bir val
belirtmek gibi bir şeydir. Peki const val
ile val
arasındaki fark nedir? const val
değeri, derleme sırasında belirlenir. Burada val
değeri program yürütülürken belirlenirken val
işlevi, çalışma sırasında bir işlev tarafından atanabilir.
Yani val
, bir işlevden değer atanabilir ancak const val
atanamaz.
val value1 = complexFunctionCall() // OK
const val CONSTANT1 = complexFunctionCall() // NOT ok
Ayrıca const val
yalnızca en üst düzeyde ve normal sınıflarla değil, object
ile belirtilen tekli sınıflarda çalışır. Bunu, yalnızca sabit değerler içeren bir dosya veya tekli nesne oluşturmak için kullanabilir ve gerektiğinde içe aktarabilirsiniz.
object Constants {
const val CONSTANT2 = "object constant"
}
val foo = Constants.CONSTANT2
2. Adım: Tamamlayıcı nesne oluşturma
Kotlin kavramının sınıf düzeyi sabitleri yoktur.
Bir sınıfın içindeki sabit değerleri tanımlamak için bunları sabit anahtar kelimelerle companion
anahtar kelimesiyle sarmalamanız gerekir. Tamamlayıcı nesne, esasen sınıftaki tek bir nesnedir.
- Dize sabit değeri içeren bir tamamlayıcı nesne içeren sınıf oluşturun.
class MyClass {
companion object {
const val CONSTANT3 = "constant in companion"
}
}
Tamamlayıcı nesneler ve normal nesneler arasındaki temel fark şudur:
- Tamamlayıcı nesneler, kapsayıcı sınıfın statik oluşturucusundan başlatılır (yani nesne oluşturulduğunda oluşturulur).
- Normal nesneler, söz konusu nesneye ilk kez geç eriştiklerinde, yani ilk kez kullanıldıklarında başlatılır.
Daha fazla yöntem vardır ancak şimdilik bilmeniz gereken tek şey, sınıflardaki sabit değerleri bir tamamlayıcı nesne içinde sarmalamaktır.
Bu görevde sınıfların davranışını genişletmeyi öğrenirsiniz. Bir sınıfın davranışını genişletmek için yardımcı program işlevleri yazmak çok yaygın bir durumdur. Kotlin, şu yardımcı işlevleri tanımlamak için kullanışlı bir söz dizimi sağlar: uzantı işlevleri.
Uzantı işlevleri, kaynak koduna erişmek zorunda kalmadan mevcut bir sınıfa işlev eklemenize olanak tanır. Örneğin, bunları paketinizin bir parçası olan Extensions.kt dosyasında bildirebilirsiniz. Bu işlem sınıfı gerçekten değiştirmez, ancak işlevi ilgili sınıfın nesneleri üzerinde çağırırken nokta gösterimini kullanmanıza olanak tanır.
1. Adım: Uzantı işlevi yazın
- Hâlâ REPL üzerinde çalışıyor, bir dizenin boşluk içerip içermediğini kontrol etmek için basit bir uzantı işlevi yazabilirsiniz:
hasSpaces()
. İşlev adının üzerinde, üzerinde çalıştığı sınıfla birlikte bulunur. İşlevin içinde,this
çağrıldığı nesneyi veit
find()
çağrısındaki iteratörü ifade eder.
fun String.hasSpaces(): Boolean {
val found = this.find { it == ' ' }
return found != null
}
println("Does it have spaces?".hasSpaces())
⇒ true
hasSpaces()
işlevini basitleştirebilirsiniz.this
açıkça gerekli değildir ve işlev, tek bir ifadeye indirilip bu ifadeye döndürülebilir. Bu nedenle,{}
etrafındaki kıvrık ayraçlara da gerek yoktur.
fun String.hasSpaces() = find { it == ' ' } != null
2. Adım: Uzantıların sınırlamalarını öğrenin
Uzantı işlevleri yalnızca yalnızca genişlettikleri sınıfın herkese açık API'sine erişebilir. private
değişkenlerine erişilemiyor.
private
işaretli bir mülke uzantı işlevleri eklemeyi deneyin.
class AquariumPlant(val color: String, private val size: Int)
fun AquariumPlant.isRed() = color == "red" // OK
fun AquariumPlant.isBig() = size > 50 // gives error
⇒ error: cannot access 'size': it is private in 'AquariumPlant'
- Aşağıdaki kodu inceleyin ve ne yazdıracağını öğrenin.
open class AquariumPlant(val color: String, private val size: Int)
class GreenLeafyPlant(size: Int) : AquariumPlant("green", size)
fun AquariumPlant.print() = println("AquariumPlant")
fun GreenLeafyPlant.print() = println("GreenLeafyPlant")
val plant = GreenLeafyPlant(size = 10)
plant.print()
println("\n")
val aquariumPlant: AquariumPlant = plant
aquariumPlant.print() // what will it print?
⇒ GreenLeafyPlant AquariumPlant
plant.print()
baskılar GreenLeafyPlant
. aquariumPlant.print()
değeri GreenLeafyPlant
olarak atandığından aquariumPlant.print()
öğesinin de GreenLeafyPlant
yazdırmasını bekleyebilirsiniz. Ancak tür, derleme zamanında çözüldüğünden AquariumPlant
yazdırılır.
3. Adım: Uzantı özelliği ekleyin
Kotlin, uzantı işlevlerine ek olarak, uzantı özellikleri de eklemenize olanak tanır. Uzantı işlevlerinde olduğu gibi, genişlettiğiniz sınıfı ve ardından bir nokta, ardından özellik adını belirtirsiniz.
- Hâlâ REPL üzerinde çalışıyorsa
isGreen
AquariumPlant
uzantısına bir renk ekleyin. Bu renk yeşilsetrue
.
val AquariumPlant.isGreen: Boolean
get() = color == "green"
isGreen
özelliğine normal bir mülk gibi erişilebilir. Bu değere erişildiğinde, değeri almak için isGreen
alanının alıcısı çağrılır.
aquariumPlant
değişkeni içinisGreen
özelliğini yazdırın ve sonucu gözlemleyin.
aquariumPlant.isGreen
⇒ res4: kotlin.Boolean = true
4. Adım: Boş değerli alıcılar hakkında bilgi edinin
Uzattığınız sınıfa alıcı adı verilir ve bu sınıfı boş hale getirmek mümkündür. Bunu yaparsanız gövdede kullanılan this
değişkeni null
olabilir. Bu nedenle, bunu test ettiğinizden emin olun. Null'a karşılık gelen bir alıcı almak istersiniz. Arayanlar, null değişkenlerde uzantı yönteminizi çağırmak istiyorsa veya fonksiyonunuz null
işlevine uygulandığında varsayılan bir davranış istiyorsanız.
- Hâlâ REPL üzerinde çalışıyor, boş bir alıcı alan bir
pull()
yöntemi tanımlayın. Bu bilgi, türden önce ve noktadan sonra soru işareti?
ile belirtilir. Gövdenin içinde, Questionmark-dot-application?.apply.
özelliğini kullanarakthis
öğesininnull
olup olmadığını test edebilirsiniz.
fun AquariumPlant?.pull() {
this?.apply {
println("removing $this")
}
}
val plant: AquariumPlant? = null
plant.pull()
- Bu durumda, programı çalıştırdığınızda herhangi bir çıkış olmaz.
plant
null
olduğundan, içprintln()
çağrılmaz.
Uzantı işlevleri çok güçlüdür ve Kotlin standart kitaplığının çoğu uzantı işlevleri olarak uygulanır.
Bu derste; koleksiyonlar hakkında daha fazla bilgi edindiniz, sabit değerleri öğrendiniz ve uzantı işlevlerinin ve özelliklerinin gücünü keşfettiniz.
- Bir işlevden birden fazla değer döndürmek için çiftler ve üçlüler kullanılabilir. Örneğin:
val twoLists = fish.partition { isFreshWater(it) }
- Kotlin,
List
içinreversed()
,contains()
vesubList()
gibi birçok faydalı işleve sahiptir. - Anahtarlar değerlerle eşlemek için
HashMap
kullanılabilir. Örneğin:val cures = hashMapOf("white spots" to "Ich", "red sores" to "hole disease")
const
anahtar kelimesini kullanarak derleme zamanı sabitlerini bildirin. Bunları en üst düzeye yerleştirebilir, tek bir nesne halinde düzenleyebilir veya bir tamamlayıcı nesneye yerleştirebilirsiniz.- Tamamlayıcı nesne,
companion
anahtar kelimesiyle tanımlanan bir sınıf tanımındaki tekli nesnedir. - Uzantı işlevleri ve özellikleri bir sınıfa işlev ekleyebilir. Örneğin:
fun String.hasSpaces() = find { it == ' ' } != null
- null alıcı, bir sınıfta
null
olabilecek uzantılar oluşturmanıza olanak sağlar. Kod yürütülmeden öncenull
kontrolü yapmak için?.
operatörüapply
ile eşlenebilir. Örneğin:this?.apply { println("removing $this") }
Kotlin belgeleri
Bu kurstaki herhangi bir konu hakkında daha fazla bilgi edinmek istiyorsanız veya takılırsanız en iyi başlangıç noktanız olarak https://kotlinlang.org adresine gidin.
Kotlin eğiticileri
https://try.kotlinlang.org web sitesinde web tabanlı çevirmen olarak Kotlin Koans adlı zengin eğitici videolar ve örnekler içeren eksiksiz bir referans dokümanı grubu bulunur.
Udacity kursu
Bu konudaki Udacity kursunu görüntülemek için Programcılar için Kotlin Eğitim Programı'na bakın.
IntelliJ IDEA
IntelliJ IDEA ile ilgili belgeler JetBrains web sitesinde bulunabilir.
Bu bölümde, bir eğitmen tarafından sunulan kurs kapsamında bu codelab üzerinden çalışan öğrenciler için olası ev ödevi ödevleri listelenmektedir. Öğretmenin şunları yapması gerekir:
- Gerekirse ev ödevini atayın.
- Öğrencilere ev ödevlerinin nasıl gönderileceğini bildirin.
- Ev ödevlerine not verin.
Öğretmenler bu önerileri istedikleri kadar kullanabilir veya uygun görebilir ve uygun olan diğer ev ödevlerini atayabilirler.
Bu codelab'de kendiniz çalışıyorsanız, bilginizi test etmek için bu ödevlerden yararlanabilirsiniz.
Bu soruları yanıtlayın
1. Soru
Aşağıdakilerden hangisi bir listenin kopyasını döndürür?
makbuz add()
makbuz remove()
makbuz reversed()
makbuz contains()
2. Soru
class AquariumPlant(val color: String, val size: Int, private val cost: Double, val leafy: Boolean)
üzerindeki bu uzantı işlevlerinden hangisi derleyici hatası verir?
makbuz fun AquariumPlant.isRed() = color == "red"
makbuz fun AquariumPlant.isBig() = size > 45
makbuz fun AquariumPlant.isExpensive() = cost > 10.00
makbuz fun AquariumPlant.isNotLeafy() = leafy == false
3. Soru
Aşağıdakilerden hangisi const val
ile sabit değerleri tanımlayabileceğiniz bir yer değildir?
▢,
normal derslerde ▢
Singleton nesnelerinde ▢
Companion nesnesinde ▢
Sonraki derse geçin:
Diğer codelab'lerin bağlantıları da dahil olmak üzere kursa genel bir bakış için Programcılar için Kotlin Eğitim Programı: Kursa hoş geldiniz başlıklı makaleyi inceleyin.