Kotlin Basic Types Part1

Arda Işıtan
8 min readSep 16, 2023

--

Öncelikle herkese merhabalar.Sizlere bugün anlaşılır ve sade bir şekilde genel hatlarıyla Kotlin nedir? neden tercih edilir ? Primitive ve Referans tipli değişkenler nedir ? değişken nasıl oluşturulur gibi soruların cevaplarını elimden geldiğince detaylı bir şekilde vermeye çalışacağım. Yazının çok uzun olup sizleri de sıkmaması adına, 2 veya 3 part şeklinde yayınlacağım.Hazırsanız hemen başlayalım.

Peki Nedir Bu Kotlin?

Kotlin, JetBrains tarafından geliştirilen ve genellikle Android uygulama geliştirmek için kullanılan bir programlama dilidir. Kotlin, Java ile uyumlu bir şekilde çalışabilen ve Java’nın yerini alabilen bir dil olarak tasarlanmıştır. 2011 yılında JetBrains tarafından geliştirilmeye başlanmış ve 2017 yılında açık kaynak olarak sunulmuştur.

Tamam,kotline şöyle kısaca bir giriş yaptık fakat asıl soru şu olmalı.

Nedir bu kotlini özel kılan maddeler ? Gelin teker teker açıklayalım.

1)Null Güvenliği: Kotlin, Null referanslarından kaynaklanan hataları önlemek için tasarlanmıştır. Değişkenlerin varsayılan olarak null olamayacağı ve null değerlerini işlemek için özel sözdizimi sağlar. Bu, NullPointerException (NPE) hatalarını önemli ölçüde azaltır ve uygulamaların daha güvenilir olmasına yardımcı olur.Bu null konusuna daha sonra değineceğim fakat Null, bir değişkenin değerinin atanmadığı veya boş olduğunu ifade etmek için kullanılan bir terimdir gibi bir tanımlama yapabiliriz.Null, biz kod yazarken umursanmayan küçük bir durum olarak görülebilir fakat bu durum programda yanlış sonuçlar çıkmasına hatta programın çökmesine kadar büyük sorunlar yaratabilir. Yukarıda da bahsettiğim gibi Null nedenli çökme durumlarında NullPointerException hatası alırız. Bu sebeple bu konu çok önemlidir ve kotlin bunu başarılı bir şekilde çözebilen bir dildir.Bu noktada Null safety kavramı tam da burda karşımıza çıkıyor.Buna başka bir yazımda değineceğim.

var name: String = "John"
name = null // Hata verir

2)İfade Odaklı: Kotlin, ifadeleri daha az yazmayı ve daha anlaşılır kodlar oluşturmayı teşvik eder. Özellikle veri sınıfları (data class) gibi özellikler, kodun daha az ve daha açık bir şekilde yazılmasına olanak tanır.

data class Person(val name: String, val age: Int)
val person = Person("John", 30)

3)İşlevsel Programlama: Kotlin, işlevsel programlamaya uygun bir dil olarak kabul edilir. Yüksek seviyede işlevsel programlama özellikleri sunar, bu da daha basit ve modüler kod yazmanıza olanak tanır.

val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }

Yukarıdaki kod örneğinde listler kullanılmıştır. Bu ayrı bir konudur fakat kısaca açıklama gerekirse val numbers adında 1,2,3,4,5 sayılarını kapsayan bir liste oluşturulmuştur.Hemen altında ise evenNumbers adında başka bir liste oluşturulmuştur.Bu noktada numbers.filter{it % 2 == 0} kodu bize numbers’ın içindeki bütün sayıları al .filter{it % 2 == 0} ile sadece 2 ile bölünebilenleri filtrele ve = ile evenNumbers’a ata demektedir..Burada it ifadesi her bir sayıyı temsil etmektedir.Farkındayım biraz kafalar karıştı fakat emin olun ilk başlarken ben de anlamakta zorlanmıştım.Bu listeler konusuna da ayrı bir yazıda değinebiliriz.

4)Java Uyumlu: Kotlin, mevcut Java kodu ile uyumlu bir şekilde çalışabilir. Bu, projelerin yavaşça Kotlin’e geçiş yapmasını kolaylaştırır. Kotlin’de Java sınıflarını kullanmak ve Kotlin sınıflarını Java’dan çağırmak mümkündür.

5)Geniş Kütüphane Desteği: Kotlin, zengin bir standart kütüphane sunar ve bu kütüphane, sık kullanılan görevleri hızlı bir şekilde gerçekleştirmenize olanak tanır. Özellikle Android uygulama geliştirme için Android Standart Kütüphanesi (Android KTX) ile entegre edilmiştir.

7)Çapraz Platform Desteği: Kotlin, farklı platformlarda kullanılabilen çok sayıda derleme hedefi sunar. Kotlin/JVM, Kotlin/JS ve Kotlin/Native gibi farklı hedefler, çeşitli platformlarda uygulama geliştirmenize olanak tanır. Bu, sunucu tarafı geliştirmenin yanı sıra web ve mobil uygulamalar oluşturmanıza da yardımcı olur.

Aslında bu maddelerin dışında öğrenirken kendi adıma farkettiğim bir nokta da kotlinin bir çok yapısı var fakat bazı dillere nazaran öğrenmesi daha kolay ve daha eğlenceli.Ben java öğrenip sonrasında kotlin öğrenmedim fakat ilk önce java öğrenip sonrasında kotline geçmek durumunda kalanların söylediği tek şey genellikle “oh be dünya varmış “oluyor 😀.Bu noktada benim düşüncem Kotlin, modern programlama dillerinin özelliklerini bir araya getirerek yazılım geliştiricilere daha verimli, daha güvenli ve daha okunabilir kodlar oluşturma fırsatı sunar. Bu nedenle Kotlin, hem yeni başlayanlar hem de deneyimli geliştiriciler için çekici bir seçenek haline gelmiştir.

Val ve Var kullanımına geçmeden önce,sizlere Referans Tipli Değişkenler ve Primitive Tipli Değişkenleri anlatmak istiyorum.

Primitive ve referans tipli değişkenler, programlama dillerinde kullanılan veri tiplerini tanımlamak için kullanılan terimlerdir. Bu terimler, özellikle nesne yönelimli programlama dillerinde sıklıkla kullanılır.

Primitive Tipli Değişkenler

  • Temel veri türlerini ifade ederler.
  • Bellekte sabit bir boyutta yer kaplarlar.
  • Doğrudan değeri saklarlar, başka bir nesneye referans olmazlar.
  • Örnek olarak byte,short,int,long,float,double,boolean ve char veri tipleri verilebilir.

Referans Tipli Değişkenler

  • Bellekte bir değerin adresini saklarlar, dolayısıyla bir nesneye referans olurlar.
  • Nesnelerin verilerine ve işlevlerine erişmek için kullanılırlar.
  • Nesnelerin kendileri bellekte farklı bir yerde saklanır.

Yukarıda gördüğünüz gibi,kotlin kısmında kodumuzu yazdıktan sonra shift+shit tuşuna basıp,çıkan arama kısmına show kotlin bytecode yazarsak kodumuzun java karşılığını bu şekilde görürürüz.Bu şekilde küçük ve turuncu boyalı şeklinde yazılan tipler Primitive Tiplerdir.

Primitive tipler,hem kapladıkları alan bakımından referans tipli değişkenlere göre daha azdır,hem de referans tipli değişkenlere göre çok daha hızlı çalışırlar.Bu sebeple biz,projelerimizde çoğunlukla primitive tiplere yer veririz.Referans tipli değişkenlere göre daha az iş yaparlar fakat çok daha hızlıdırlar.

Fakat yukarıda gördüğünüz gibi Kotlin tarafında değişken tiplerinin üzerine gelip CTRL+ Sol Click yaparsak bu veri tiplerinin aslında bir class olarak tutulduğunu görürüz.Java ve diğer birçok dilde primitive değişkenler görülürken,kotline baktığımızda tüm değişken tipleri bir classtır.Peki Kotlin’de herşey(değişkenler dahil) birer class ise,primitive tipler kotlinde kullanılmaz mı ?

Kotlinin resmi dökümantasyonuna baktığımızda da karşımıza çıkan ilk cümle,Kotlinde her şey birer nesnedir cümlesidir. Yani yukarıdaki görsellerde yer alan class tipindeki değişkenler, çalışma zamanında yapılan özel optimizasyonlarla java tarafındaki gerçek primitive karşılıklarına dönüştürürler.

Şimdi bu görsele tekrar bakalım, işte bizim kodları show kotlin bytecode yapıp Kotlin tarafında oluşturduğumuz değişkenlerin tiplerini, Java tarafında da primitive şeklinde görmemizin sebebi de tam olarak budur.

Val-Var Kullanımı

Kotlinde bir değişken tanımlamadan önce değişken isminin önüne mutlaka var veya val keywordu’unu koymamız gerekiyor. Kotlin’de val ve var iki farklı değişken tanımlama anahtar kelimesidir ve bu anahtar kelimelerin kullanımı değişkenin davranışını belirler.

Var Kullanımı(Variable)

  • var, değişkenin değerini herhangi bir zamanda değiştirebileceğiniz (mutable) bir değişkeni tanımlar. Yani, değişkenin değeri sonradan değiştirilebilir.
  • Genellikle dinamik verileri veya bir değişkenin değerinin sürekli değişebileceği durumlar için kullanılır.
  • Mutable(Değişebilir) olarak da isimlendirebiliriz.
var age = 30
var userName = "Alice"

var age=20
var userName="John"
//Burada var ile tanımlanan age ve userName değişkenlerinin değerlerini sonradan değiştirebilirim.
//IDE bu durumda hata vermeyecektir.

Val Kullanımı(Value)

  • val, değeri bir kez atanabilen (tek değerli) bir değişkeni tanımlar. Yani, bir kez başlatıldıktan sonra değeri değiştirilemez.
  • Değerin değiştirilemez olması, kodun daha güvenli olmasını sağlar, çünkü bir kez atandığında yanlışlıkla değiştirilme riski ortadan kalkar.
  • Özellikle sabit değerler veya bir nesnenin özellikleri gibi değişmesini istemediğiniz veriler için kullanışlıdır.

val name = "John"
name="Mike" //name değişkeninin val ile tanımladığım için IDE bana hata verecektir.

val age = 24
age = 30 // Yukarıdaki name değişkeni gibi age değişkenini de val ile tanımladığım için değerini sonradan değiştiremem.
// Val cannot be reassigned hatası alırım.

Burada ek olarak bir bilgiden bahsetmek istiyorum.

val değişkenlere biz genel olarak immutable değişkenler deriz.Aslında bu yanlış bir ifadedir.Val değişkenler,readonly değişkenlerdir.

readonly demek değeri okunabilen, fakat ilk değer atamasından sonra tekrar değer atanamaz(set edilemez) demektir.

immutable ise,bir değişkenin/nesnenin durumu asla ilk değerden farklı olamaz demektir.

class Box {
var width: Int = 20
var height: Int = 40
var length: Int = 50
var usedSpace: Int = 0

val availableSpace: Int
get() {
return (width * height * length) - usedSpace
// Degiskenin degeri,buradaki ozelliklere gore degisebilir.
// Bu sebeple val degiskenler immutable degil,read only'dir.
}
}

fun calculateAvailableSpace() {
val box = Box()
box.height = 10
box.width = 20
box.length = 5
box.usedSpace = 2

println(box.availableSpace) // Farklı sonuç alırız.

println("----------------------")

box.height = 30
box.width = 10
box.length = 8
box.usedSpace = 0

println(box.availableSpace) // Farklı sonuç alırız.
}

Yukarıdaki örneği dikkatle incelersek,avaliableSpace adında val bir değişken tanımladık.Get() fonksiyonuyla bu değişken bize belli parametrelerin işleminin sonucunu dönüyor.Burada açıklamak istediğim şey,biz bu parametrelerin değerlerini değiştirdiğimizde avaliableSpace değerinin değeri değişebilir.Bu sebeple val değişkenler immutable değil,readonly değişkenlerdir.

Performans konusuna gelecek olursak,val ile var değişkenler arasında bir performans farkı bulunmuyor denebilir.Yine de akademik seviyede konuşuyorsak,var değişkenler “readonly” gibi bir şarta sahip olmadıkları için gözardı edilebilecek kadar ufak bir farkla val değişkenlere göre daha performanslıdır.

Fakat projemizde multi-thread işlemler varsa, bu işlemlerde kullanılan değişkenlerin birbirlerinin son durumlarını kontrol etme ihtiyacının yarattığı maliyet çok daha ciddi performans sorunlarına yol açmaktadır.Bu sebeple genel kabul,val değişkenlerin, var değişkenlerden daha performanslı olduğu yönündedir.

Best Practice olarak bir değişkeni val ile tanımlamak,sonrasında eğer değişkenin değerini değiştireceksek var’a çevirmek daha mantıklı ve kullanışlıdır.Bu sayede kod yönetimimiz daha kolay olacaktır.

Değişken Tanımlama

Kotlinde değişken tanımlarken 2 farklı şekilde tanımlayabiliriz.

Yukarıdaki gibi bir üstte öğrendiğimiz var keywordu,değişkenin adı,atama operatoru ve değişkenin değerini vererek tanımlayabiliriz.

2. olarak bu şekilde de tanımlayabiliriz.Burada üstteki tanımlamadan farklı olarak :(tür belirteci) ve değişkenini türünü de belirttik.Aslında bunu yapmak zorunda değiliz.Bazı durumlarda yapmamız belki faydalı olabilir fakat kotlinde type inference olduğundan dolayı bunu yaptığımız zaman redundant(gereksiz) uyarısı alırız.Tamam anladım,type inference falan yazıyorsun fakat nedir bu açıkla dediğiniz duyar gibiyim.Hemen açıklayalım..

Type Inference(Tip Çıkarımı)

Type Inference en basit tanımıyla değişkenlerin tanımlanması sırasında tip belirtmeden,derleyicinin verdiğimiz değere bakarak değişkeninin türünü çıkartmasıdır diyebiliriz.Hemen örneğimize bakalım.

Gördüğünüz gibi,ilk örneğimizde name değişkenine bir isim değeri atadık.Değişkenin tipini belirtmememize rağmen derleyici otomatik olarak name değişkeninin tipini String olarak bize gösterdi.

Buradaki örneğimizde de bir adet age değişkeni tanımladık,değişkenin tipini Int olarak belirttik ve 20 değerini değişkenimize atadık.Gördüğünüz üzere Int’ın üzeri hafif silik olarak gözüküyor.Üzerine geldiğimizde ise Explicitly given type is redundant here diyor,yani age’ın veri tipinin açıkça belli olduğunu ve herhangi bir tip belirtiminin gereksiz olduğunu belirtiyor.

Burada değinmek istediğim bir önemli nokta daha var. Bu kısımda,Numbers tiplerinde farklı bir durum vardır.Type Inference sırasında eğer tanımladığım sayı,Int veri tipinin aralığından büyük değilse,veri tipi default olarak Int olur.Fakat eğer Type Inference sırasında tanımladığım sayı,Int veri tipinin aralığından büyük ise tipi default olarak Long olur.Şimdilik burda yeri gelmişken değinmek istedim fakat serimizin 2. partında sizlere bunu örnekle göstereceğim.

Not

Kotlin’de veri tipini belirtmeden iş yapabiliriz, ancak projemiz büyüdükçe bu yaklaşım bize zarar verebilir. Küçük değerlerle çalışıyorsak ve değer aralığını biliyorsak, bu değerleri belirli türlerle (örneğin, Byte) tanımlamak, projenin daha iyi yönetilmesine ve daha az bellek tüketmesine yardımcı olabilir. Bu yaklaşım, projemizin büyümesi açısından ileride bize fayda sağlayabilir.Yani sonuç olarak maksimum performansı almak için, doğru veri tipini kullanmamız gerekmektedir.

Son Güncelleme :16.02.2024

Yazımı okuduğunuz için çok teşekkür ederim.Bu yazıyı yazarken Gökhan Öztürk’ün derslerinden ve kendi notlarımdan yararlandım.Yazımızın diğer partında ise değişken tipleri ve type conversion konularına detaylı bir şekilde değineceğim.Linkedin ve Github hesabımdan beni takip edebilirsiniz.

Linkedin:https://www.linkedin.com/in/ardaisitan/

Github:https://github.com/ArdaIstn

--

--

Arda Işıtan

Elektrik-elektronik mühendisliği mezunuyum.Android-Kotlin alanında kendimi geliştirmeye devam ediyorum.