Neden Kotlin Kullanmalıyız?

Kotlin, hızlı derlenir, daha güvenli kod yazmayı sağlar, basit ve sade bir syntaxe sahiptir ve uygulamaların boyutunun artmasını engeller. Kotlin ile yazılan kod parçaları daha kısa ve daha az ayrıntılıdır bu da daha az hata yapabileceğiniz anlamına gelir. Kotlin, Java dilinden ilham alan bir dildir ancak pek çok farklı ek özellik içeren geliştirilmiştir bir sürümdür. Android uygulamarı geliştirmek için Kotlinde bulunan temel yapı ve temel kavramları bilmek gerekir. Daha önce Java ile proje geliştiren biri olarak kotlin öğrendikten sonra bir daha asla Java kullanmak istemeyebilirsiniz :)

Kotlin Temel Syntax

Değişken Tanımlama

Kotlin’de değişkenleri tanımlamak için iki anahtar kelime bulunmaktadır. val ve var

  • val değeri asla değişmeyen değerler için kullanılır.
  • var değeri değişebilen değerler için kullanılır.

Değişkenin değeri 15 olan Int tipinde bir değişken tanımlayalım.

var count: Int = 15

var anahtar kelimesi count değişkenine yeniden değer atayabileceğiniz anlamına gelir.

var count: Int = 15
count = 20

Örnek olarak değeri değiştirilemeyen bir değişken oluşturalım.

val language: String = "Kotlin"

Tip Çıkarımı

Kotlin derleyicisi atanan değerin türüne bağlı olarak değişkenin türünü bulabilir.

val language = "Kotlin"
val upperCaseName = language.toUpperCase()

Değişkenin türünün String olduğunu belirtmeden yukarıdaki şekilde de kullanabiliriz.

Null Kontrolü

Kotlinde bulunan tip sistemi, NullPointerException hatasını ortadan kaldırmayı amaçlar. Özellikle Java dahil bir çok programlama dilinde null bir nesneye erişmeye çalışırken NullPointerException hatası ile karşılaşılmaktadır. Bu yüzden Kotlin’de referans tipleri null (boş olabilen) yada non-null (boş olamayan) olarak 2’ye ayrılır. Örneğin, String tipindeki bir değişken null olamaz.

var language: String = "Java" 
language = null // hata oluşur

Boş bir değer tutmak için değişkenin tipi String? olarak belirtilmelidir. Yani, null olabilecek değişkenlerin sonuna ? eklemek gerekmektedir.

var newLanguage: String? = "Kotlin" 
newLanguage = null // hata oluşmaz

Null Olabilen Değişkenlerin Kontrolü

1. if ile kontrol

Kotlin’de null olabilen değişkenleri kontrol etmek için bir çok yöntem bulunmaktadır. Diğer dillerde sıklıkla kullandığımız if ile null kontrolü yapmaktır. Örnek olarak null olabilen bir değişken tanımlayarak değişkenin null olup olmadığını direkt olarak kontrol edelim.

val nullableValue: String? = "Hello World"

if(nullableValue != null && nullableValue.length > 0) {
    print("Değişkenin uzunluğu ${nullableValue.length}") 
}
else {
    print("Boş string")
}

NOT: if ile kontrol işlemi sadece val olan yani değeri asla değiştirilemeyen değişkenlerde çalışır. Aksi takdirde nullableValue değeri kontrol işleminden sonra null olarak atanabilir.

2. Safe call operatörü ?.

Null olabilen bir değişken üzerindeki özelliğe erişmek için kullanılabilen ikinci yöntem ise safe call operatörünü ?. kullanmaktır. Önce null olabilen bir değişken tanımlayarak safe call operatörünü kullanmadan değişkenin özelliklerine erişmeye çalışalım.

    val b: String? = null
    println(b.length)

Kodu çalıştırdığımızda null olabilen bir değişkenin özelliğine erişmek için safe call operatörünü kullanmalısınız uyarısı gelecektir. Şimdi de safe call operatörünü ekleyerek kodu çalıştıralım.

    val b: String? = null
    println(b?.length)

b değişkeni null olmasına rağmen kodu çalıştırdığımızda herhangi bir hata ile karşılaşmadık. Böylece olası NullPointerException hatasını engellemiş olduk.

Yalnızca null olmayan değerler üzerinde işlem yapmak için let kullanılmaktadır. a ve b değişkeni null değilse çıktı yazdıralım.

val a: String? = null
a?.let {
    println("a değişkeni null olduğu için çalışmaz")
}
    
val b: String? = "Kotlin"
b?.let {
    println("bu değer null değildir")
}

3. Elvis Operatörü ?:

Atama işlemi gerçekleştirilirken, atanan değer null olabilen bir değerse; değeri null değilse değişkenin kendisini null ise farklı bir değer atanmasını sağlar. Basit bir örnekle ne demek istediğimizi anlayalım.

val a: Int = if (b != null) b.length else -1

b değişkeninin değeri null değilse b’nin uzunluğunu, null ise -1 değerini atama işlemi gerçekleştirdik.

Uzun uzun if kullanmak yerine, elvis operatörünü (?:) kullanarak aynı işlemi gerçekleştirelim.

val a: Int = b?.length ?: -1

?: ifadesinin solu boş değilse elvis operatörü o değeri döndürür, aksi takdirde sağ tarafta bulunan ifadeyi döndürür.

4. !! operatörü

NullPointerException hatası almak isteyenlerin kullandığı bir yöntemdir. Değişkenleri null olmayan tipe dönüştürür fakat değişkenin değeri nullsa hata fırlatır.

val nullable: String? = null
nullable!!.length //hata fırlatır

Paket Tanımlama ve İçe Aktarma

Paket tanımlama işlemleri dosyanın en üst satırında bulunmalıdır.

package my.demo

import kotlin.text.*

Standart Çıktıya Yazma İşlemi

print girilen veriyi standart çıktıya yazdırır.

print("Hello")
println("World")

println girilen veriyi standart çıktıya yazdırır ancak bir satır sonu ekler. Böylece daha sonra yazdırılan veri bir sonraki satırda listelenir.

Fonksiyon Tanımlama

Dönüş türü olmayan fonksiyon.

fun write(): Unit {
    print("hello")
}

Kotlin’de bulunan Unit, Java’daki void’e karşılık gelir ancak kullanılması isteğe bağlıdır. Aynı fonksiyonu Unit kullanmadan da yazabiliriz.

fun write() {
    print("hello")
}

Dönüş türü Int olan ve parametre olarak iki adet Int değişken alan fonksiyon.

fun sum(a: Int, b: Int): Int {
    return a + b
}

Sınıf ve Örnek Oluşturma

Bir sınıf oluşturmak için class anahtar kelimesi kullanılır.

class Animal

Constructor Oluşturma

Constructor, bulunduğu class’dan nesne üretimi sırasında çalışacak olan metoddur. Bir sınıf oluştururken constructor tanımlamasak bile içerisinde default olarak constructor bulunur. Kotlin dilinde bir sınıf primary constructor ve bir veya birden fazla secondary constructor‘a sahip olabilir.

1. Primary Constructor (Birincil kurucu)

Aşağıda name adında parametre alan bir primary constructor örneği bulunmaktadır. Primary constructor tanımlamak için constructor anahtar kelimesi kullanılır.

class Animal constructor(name: String) { /*...*/ }

Eğer herhangi bir annotations (@Inject) yada visibility modifiers (public, protected, private) kullanılmıyorsa constructor anahtar kelimesinin kullanılmasına gerek yoktur.

class Animal(name: String) { /*...*/ }

Her iki şekilde de constructor tanımlanabilir.

Primary constructorlar herhangi bir kod bloğu içermezler. Bu yüzden kod yazmak için initializer block kullanılır. init anahtar kelimesi kullanılarak tanımlanır.

class Animal constructor(name: String) { 

    init {
        println("animal name ${name}")
    }

}

Constructor parametrelerinin başına eklenen val ve var sayesinde Kotlin compiler name ve speed adında property’leri otomatik olarak oluşturur.

class Animal constructor(val name: String)

fun main(args: Array<String>) {
    val animal = Animal("karabas")
    println("${animal.name}") 
}

2. Secondary Constructor (İkincil Kurucu)

Secondary constructorlar, constructor keywordü kullanılarak tanımlanır.

class Animal {
    var name: String
    
    // Secondary Constructor
    constructor(name: String)  {
        this.name = name
    }
}

Secondary constructor, primary constructor ile birlikte kullanılabilmektedir. Fakat bir sınıf içerisinde hem primary constructor hemde secondary constructor bulunuyorsa this() kullanarak primary constructor’ı işaret etmek (delegate) gerekmektedir. Aşağıdaki örnekte hem primary constructor hemde secondary constructor bulunmaktadır.

class Animal(var name: String) {
    var age: Int? = null

    // Secondary Constructor
    constructor(name: String, age: Int): this(name)  
    {
        this.age = age
    }
}

fun main(){
    // Primary constructor 
    val animal = Animal("Karabaş")
	println("${animal.name}")
    println("${animal.age}")
    // Secondary constructor
    val animal2 = Animal("Köpük", 2)
    println("${animal2.age}")
} 

Görüldüğü üzere primary constructor örneğinin age property’i null, secondary constructor örneğinin ise 2’dir.