Kotlin Property vs. Field

Didem Ozturkler
IBTech
Published in
5 min readMar 20, 2023

Merhaba, bu yazımda Kotlin’de bir çok yapının temelinde kullanılan detay ama önemli bir konudan bahsedeceğim. Hazırsanız özellikle Java’yı az çok bilenler için her şeyi başlatan bir soruyla konuya giriş yapmak istiyorum :)

Java’da her şey default olarak private iken Kotlin’de neden public? Ve bu durum encapsulation’a bir problem teşkil etmiyor mu? Her şey public iken Kotlin encapsulation’ı nasıl sağlıyor?

Şimdi bu sorulara cevap bulmaya çalışalım.

Özellikle Java ile başlayıp Kotlin’i sonradan öğrenenler için Java’dan gelen alışkanlık gereği classın içindeki bir değişkenden bahsederken buna field, variable ya da değişken deriz çünkü Java’daki isimleri zaten budur. Ancak bunlar Kotlin için doğru kavramlar değil. Çünkü Kotlin’de fieldlar yoktur, “property” ler vardır. Property dediğimiz şey ise aslında bir değişkenin get ve set metodlarıdır.

Get ve set’i java özelinde açıklayacak olursak;

public class FinancialSituationJava {

int asset = 100000;

public int getAsset() {
return asset;
}

public void setAsset(int asset) {
this.asset = asset;
}
}

Soruda da belirttiğim gibi Java’da tanımlanan değişkenler eğer visibility modifier belirtmezsek default olarak private’tır ve dolayısıyla encapsulation’ı sağlamak için get-set metodları da örnek koddaki gibidir. Yani burada asset değişken (variable veya field da diyebiliriz), getAsset ve setAsset ise bu değişkene erişen propertylerdir veya bu değişkenin propertyleridir diyebiliriz.

Kotlin’de ise arka planda bulunmasına rağmen aslında hiçbir zaman değişken-field tanımlamıyoruz. Bizim değişken gibi tanımladığımız şey aslında bir propertydir.

Java’nın aksine Kotlin’de kendimiz private tanımlamadığımız sürece default visibility modifier public’tir.

Girişteki sorumuzu biraz daha açalım :) Encapsulation’da değişkenlerin private tanımlanması ve buna erişecek olan propertylerin get ve set metodlarının yazılması gerekirdi fakat Kotlin’de her şey public. Neden?

Özellikle java’dan gelenler için iki dil arasındaki farkları görebilmek adına henüz bilmeyenler için Android Studio’nun sunduğu Show Kotlin Bytecode özelliğini kullanmanızı tavsiye ederim. Kotlin’e Java’dan geçen biri olarak bir çok kavramı anlamdırmam konusunda kendim de çok faydasını gördüm.

Tüm projede Show Kotlin Bytecode diye arattığımızda

Solda yazdığımız Kotlin kodunun sağda byte koda çevrilmiş halini, Decompile’a tıkladığımızda ise aşağıda Java’ya çevrilmiş halini görebiliriz.

Bu kısa bilgilendirmeden sonra örneğimize geçecek olursak, soldaki Kotlin classımızı önce bytecode’a ardından decompile ederek Java koduna çevirdiğimizde sağdaki çıktıyı alırız.

Yukarıdaki iki kod parçasına baktığımızda ikisinin de ürettiği assembly kodu aynıdır, dolayısıyla aslında iki kod da birbirinin dengidir.

Kotlin’de visibility modifierını belirtmediğimiz sürece tanımladığımız her değişken default olarak publictir demiştik. Dolayısıyla 4.satırda var asset şeklinde tanımladığımız değişken de public’tir. Ancak bunun Java karşılığına baktığımızda asset değişkeni private olarak görülüyor (13. satır) ve bu değişkene erişen public get-set metotları bulunuyor (Java Encapsulation).

O halde burda şöyle bir yorum yapabiliriz : Biz Kotlin’de public bir değişken tanımlasak bile bunun makine kodu; private bir değişken ve bu değişkene erişen public get-set metodlarını içeriyor olacak. Bu yüzden biz burada public bir asset değişkeni tanımladığımızı zannederken arkaplanda asset aslında private tutuluyor ve bunun public get-set metodları yazılıyor. Bu sebeple Kotlin’de tanımladığımız asset, field değil bir property’dir. Yani var asset’in tanımına karşılık gelen yer aslında getAsset-setAsset metodlarıdır. Dolayısıyla sorumuza cevap olarak da Kotlin’de public tanımlanan değişkenler encapsulation’a bir sorun teşkil etmez.

Kotlinde bazı durumlar dışında field kısmına erişemeyiz, bizim aslında işlem yaptığımız kısımlar property kısmıdır.

Java’da değişkeni direkt public yaparak encapsulation’ı aşabiliriz fakat Kotlin’de değişkeni public de yapsak private da yapsak encapsulation’ı aşamayız. Çünkü bu değişken her durumda arkaplanda private olarak yazılır. Dolayısıyla gerçek anlamda Java’da kullanılabilen ve değişken-field dediğimiz şey Kotlin’de her zaman private’dır ve bunu da kod yazarken değil de o kodu makine diline çevirdiğimizde görebiliriz.

Bu arada aklımıza şöyle bir soru gelebilir. Öyleyse Kotlin’de değişkeni tanımlarken public veya private olması neyi değiştiriyor?

Bunu da daha açık görebilmek için classımıza bir de private şeklinde bir debt değişkeni tanımlayalım ve Show kotlin bytecode ile decompile edip Java halini görelim.

Sağdaki Java halinde de değişkenimiz yine private fakat gördüğünüz gibi önemli bir fark olarak getDebt-setDebt fonksiyonları oluşturulmadı. Yukardaki sorumuza cevap olarak bir değişkeni private tanımlamak arkaplanda o değişken için üretilen get-set metodlarının olup olmamasını belirliyor, diyebiliriz.

Özetleyecek olursak Kotlin’de tanımladığımız bir değişkeni public yapmak arkaplanda get-set metodları olsun, private yapmak ise get-set metodları olmasın anlamı taşımaktadır. Bu sebeptendir ki Kotlin’de bunlara field değil property deniyor. Ayrıca değişkeni val yaptığımızda ise arkaplanda yalnızca get metodu oluşturulur ek bilgisini de vermek isterim.

Kotlin’in bir başka önemli yapısı olan Extension fonksiyonlarda da bir classa extension fonksiyon yazabildiğimiz gibi extension property de yazabilmemizin sebebi yine propertylerin aslında get ve set metodlarından oluşmasından dolayıdır. Bunu da aşağıdaki örnek görsel ile açıklayalım.

Burada type değişkenini önüne receiver classı vererek extends ettik. Bunu yapabilmemizin sebebi aslında type bir variable-field değil, getType ve setType fonksiyonudur. O yüzden biz Kotlin’de bir değişkeni de extends edebiliriz çünkü değişken dediğimiz şey propertydir ve get-set metotlarından oluşur, değişkenin kendisi değildir. Yani bu type’ı extends edebilmemizin sebebi type’ın aslında getType ve setType metodlarından oluşuyor olmasıdır.

Ayrıca var Account.type = “kmh” şeklinde direkt bir değer ataması da yapılamaz. Bunun sebebi kodu decompile edip Java’ya çevirdiğimizde type adında bir değişkene rastlayamamamızdan kaynaklıdır çünkü type değişkeninin backing fieldı yoktur.

Özetle Kotlin’de bildiğimiz anlamıyla bir değişken yani property de extension olarak yazılabilir. Bu sayede Account classından oluşturduğumuz bir nesne üzerinden type değişkenini de kullanabiliriz.

var account = Account()
account.type = "term account"

Bu yazımda genel olarak property ve field kavramlarının ne olduğundan ve aralarındaki önemli farklılıklardan bahsettim. Bu iki kavram arasındaki farkın tam olarak ne olduğunu anlamak eminim ki Kotlin’de bir çok önemli yapının temelini anlamamıza da katkı sağlayacaktır. Umarım faydalı olmuştur. Bir başka yazıda görüşmek üzere :)

--

--