Part 1: Temel Syntax üzerine bir söylence

Bu derste temel Kotlin okur yazarlığına giriş mahiyetinde, değişkenler-sabitler, fonksiyonlar ve şu dilden düşmeyen “nullable “ üzerine birkaç kelam edeceğiz. Zaman zaman parantez içerisinde İngilizce’ de kullanılan karşılıklarını vereceğim. Bir dil kendi jargonunu yaratır ve bunları bilmekte fayda var. Bu arada ben hem çalışırken hem de bu dökümanı hazırlarken Kotlin Koans online ‘ dan çok faydalandım. Aşağıda verdiğim kod parçacıklarını copy paste yapın,farklı senaryolar deneyin. Çok daha hızlı ve kalıcı bir öğrenme olacaktır. Hızlıca sadece bu ders kapsamını baz alarak, Kotlin neleri geride bıraktı bir bakalım:

  • Elveda noktalı virgül : Compile eder ama kullanmayalım ne gerek var.
  • Primitif tiplere elveda: Burada herşey obje .Yani mesela artık double yok sadece Double var.
  • void yok : İstersen Unit var. Ama onu da kullanmasan olur.

Variable ve Value

Bir değişken tanımlamak istiyorsak var (mutable )ile , bir sabit tanımlamak istiyorsak bunu yolu val (immutable/ read-only) ile yapıyoruz. Bunların hepsini de artık obje diye adlandırıyoruz.

val aslında Java da kullandığımız final ile aynı.

Peki nasıl tanımlarız bir değişkeni ya da sabiti? Birden fazla seçenek mevcut Şöyle ki:

  • Explicit ya da immediate olarak, yani objenin tipini, objeyi oluştururken söyleyebiliriz. Int türünde bir sabit tanımlayalım ve değerini atayalım:
val price : Int = 3;
  • val bir sabittir ona tekrar değer atamaya kalkarsam compile hatası verir.
price = 5 ; // (val can not be reassigned)
  • Obje tipini yazmaya bilirsin. Zaten compiler atadığın değerden onun tipini belirleyecek. Fakat sizinde hak vereceğiniz gibi bir değer atanmadıysa (initialize ) bu söylediğim geçerli olmayacaktır. Çünkü compiler’a objenin tipini bulması için bir şey söylememiş olduk.
val sayı = 5      // Int olduğunu anladı.
var name = "Roz"  //Değişken tipini String olarak atadı bile.

val c : Int 
c= 3 // herşey yolunda
  • Bir obje Long ise Long, Int ise Int’tir . Yani demem o ki bir değişken tipini başka bir değişken tipine atayamayız. Java implicit dönüşüme izin verir. Ama Kotlin vermez. Casting konusunda bunlara daha çok değineceğiz.
val x: Int = 20
val y: Double = x  // OPS! Buna izin verilmez. 
Java ne yapardı:
int x = 3; // 4 byte' lık yer ayırdı.
long y =x ; // 8 byte 'lık yer ayırdı. 4 bytelık bir veriyi 8 byte'a taşıdığım için hiçbir sorun çıkarmadan Java bunu gerçekleştirir.

NOT:

  • İşin uzmanları diyor ki eğer objenin değerini değiştirmeyeceksen en baştan val diye tanımla. Bu sayede kendimizi daha güvende hissedeceğiz :)
  • Bunu da söylemiş olalım:
var :  getter ve setter default olarak oluşturuldu bile.
val : sadece getter oluşturuldu. İstersen setter'ı oluştur.

Fonksiyonlar

Fonksiyonları 4 farklı şekilde tanımlayacağız: named (ordinary function), lambda, extension, and infix. Şimdi sadece genel özelliklerinden bahsedelim.

  • ”fun” ile başlıyoruz tanımlamaya. “( )” içine parametreleri yerleştirdik. Daha sonra “iki nokta : “ bırakıp fonksiyonun bize ne tipte değişken döndüğünü yazıyoruz. “{} “ içine de fonksiyon ne yapsın istiyorsak yazıyoruz.
fun sum(a: Int, b: Int): Int {
return a + b
}

Şimdi bir de neleri yapıp yapamayacağımıza bakalım:

  • Az yukarda objeyi tanımlarken değişkene değerini atadıysak değişken tipini vermesek bile pek akıllı compiler’ın onun tipini bileceğinden bahsetmiştik. Aynı şey burada da geçerli. Yani geri dönüş (return) değerini vermesekte olur. Bu arada tek satırda vereceğimiz ifadeler için süslü parantez kullanmayabiliriz.
fun sum(a: Int, b: Int) = a + b  // inferred return type deniyor(yani sen yazmasanda Int sonucunu çıkarıyor demek)
!!
fun sum(a: Int, b: Int) = return a + b
// bu ifade hata verecektir. return ibaresini kullanıyorsak tipi belirtmeliyiz VE süslü parantezide kullanmalıyız.
  • Fonksiyonun herhangi bir geri dönüş değeri yoksa bir şey yazmasakta olur. İlla yazacağım diyorsanız : Unit .
fun topla(a: Int, b: Int) {
println(“$a ve $b yi toplarsan ${a + b} bulursun”)
}
  • Evet pek dikkatli okurlar. String içinde verdiğimiz değişkenler gözünüzden kaçmadı biliyorum. $ işareti ve {} ile bu işide halledebiliyoruz. Nasılını aşağıdaki örnekle daha iyi anlayacağız.
val i = 10
val s = "i = $i" // çıktı-> "i = 10"

Süslü parantezi nereye konumlandırdığımız önemli :

val s = "abc"
val str = "$s.length is ${s.length}" // çıktı-> "abc.length is 3"

Nullable ve Non-Null Tipleri

Eveeet. Geldik milyon dolar kazandıracak Kotlin’in çok bahsedilen özelliğine. “NullPointerException” hatalarının önüne geçmek için bazı kaideler var burada.

Nullable Type Nedir ?

Objeleri null olabilen ya da olamayan diye tanımlayabiliyoruz. Hem de sadece ? ile. Yani ? işareti varsa compiler diyoki tamam bu null olabilir senin bundan haberin var o zaman benim için de tamamdır.

var a: String = “abc”
a = null // error !! a'yı non-null olarak tanımlamıştık, hata aldık.

var b: String? = "abc"
b = null // Sorun yok .

Şimdi bir de başka bir konuya değinelim .

val l= a.length  // Zaten null olamayacağı için rahatlıkla çağırabilirsin. 
//E burada sorun yok sorun aşağıda 
val l = b.length // b= null demiştik dolayısı ile error!!

Bu sorunun da üstesinden geleceğiz. Birden fazla yolu var:

  1. If check: Bunu biliyoruz zaten. null sa şöyle yap değilse böyle yap. Müsaadenizle geçtim burayı.

2. Safe Call : Diyelim ki b nin tipi nullable oldu ve dolayısı ile biz bu değişkene null atayabildik. Bu olayı bir zincir gibi düşünelim, b’nin uzunluğunu elde etmek istediğimizde aynı null kontorolünü burada da yapmalıyız.

var b: String? = “abc”
b = null // ok
b.length   // error!!
b?.length // Sorun yok. b null değilse b.length'e döner ,eğer null ise null dönecektir.

Bu olay zincirleme ifadelerde kullanışlı olacaktır.

var gezegen: String = null   // 
evren?.gezegen?.Dünya?.insan?.isim? // çıktı-> null
evren?.gezegen.Dünya?.insan?.isim?  //çıktı-> kotlin.KotlinNullPointerException

3. Elvis : Siz suspicious minds’ ları hemen şimdi aydınlatıyoruz ;)

“?:” önce sola bakar eğer null değilse soldaki değeri alır . Ama eğer solda gördüğü değer null ise sağına döner ve onu alır.

val r= b?.length ?: -1
// b?length= null ise r= -1; değilse b'nin uzunluğuna döner.

4. !! operatörü: Bitmeeez. Bu null pointer nasıl zarara uğrattıysa hertürlü önlem alınmış. Bu da nesi derseniz, burda da bilerek isteyerek null pointer hatası almamız sağlanıyor.

var b :String? = null
val l = b!!.length // kotlin.KotlinNullPointerException

5. Safe Cast: Bunu direk koddan açıklayalım.

var b:Double = 0.21
val a: Int? = b as? Int  // Git bir bak eğer b Int ise al       değerini a' ya ata.
println(“$a + $b”) //  null + 0.21
Diyelimki ? bırakmadık unsafe cast yapmayı denedik 
val a: Int? = b as Int
println(“$a + $b”) //   java.lang.ClassCastException: hatasını alırız.

Bu ders için söyleyeceklerimiz bu kadar olsun. Parmaklarımızı daha az yoracak Kotlin’le tanıştık, sevdik mi sevdik bence. Bir sonraki derste fonksiyonlar ve classlar üzerine daha çok şey söyleyelim. Bir de GitHub’a örnek proje iliştirelim.

O zaman Hasta la vista mi amigos!