Kotlinde Fonksiyonlar-1

İsmail Talha DENGİZ
5 min readMar 30, 2020

Fonksiyonlar bizi tekrar tekrar aynı kodu yazmaktan, karmaşıklıktan kurtararak daha temiz ve daha doğru kod yazmamızı sağlayan yapılardır. Diğer yazılarımda kod yazarken de gördüğümüz fun main() fonksiyonundan bir fonksiyon nasıl tanımlanır bir bakalım.

  • Fonksiyonlar fun keyword’ü ile başlar.
  • Daha sonra fonksiyonumuza bir isim veririz.
  • Sonrasında ise parametre parantezleri bulunur. Duruma göre varsa parametreleri bu parantezler arasına yazarız. (Parametre yazarken ise önce parametrenin ismi sonrasında tipi belirtilir.)
  • Eğer fonksiyonumuzun bir geri dönüş tipi olacaksa parametre parantezlerinden sonra : ve dönüş tipini yazarız. (Geri dönüş değeri verilmeyen fonksiyonlar unit tipini geri döndürür.)
  • Tüm bu adımlardan sonra { } ile fonksiyon bloğu açılır ve kapatılır. Fonksiyonun yapacağı iş bu parantezler arasına yazılır.

Fonksiyonumuzu tanımladık. Bu fonksiyonu kullanmak istediğimiz yere çağırırken ise:

  • Fonksiyonun ismi yazılır.
  • Varsa parametre parantezleri içerisine parametresi yazılır, yoksa boş bırakılır.

Şimdi tüm bunları basit bir örnek üzerinde görelim.

Fonksiyon tanımı ve çağırımı

Fonksiyona birden fazla parametre gönderebiliriz. Aşağıdaki örnekte println içerisinde iki parametre alan fonksiyonumuzu çağırdık ve kullanıcıdan gelen değerleri parametre olarak göndererek fonksiyon içerisinde gerçekleşen işlemin sonucunu ekrana yazdırdık.

Aynı isimde birden fazla fonksiyon tanımlayabiliriz fakat bu fonksiyonların ya parametre sayısı ya da parametre tipleri farklı olmalıdır. Bu işleme fonksiyonu overload etme işlemi denir. Kotlin ise aynı isimle fakat farklı parametre sayısı veya tipiyle fonksiyonu overload ederek kullanmak yerine, parametreyi default değer vererek daha az kodla aynı işi yapmamızı sağlar. Bu aşamada ise bilmemiz gereken iki kavram daha ortaya çıkıyor. Default Argument ve Named Argument. Bu iki kavramı açıklamadan önce Java mantığı ile kotlinde fonksiyon overload işlemini görelim. Aşağıdaki örnekte farklı parametre sayısına sahip dört fonksiyon tanımladık ve main bloğu içerisinde her birine parametrelerini vererek fonksiyonları çağırdık. Şimdi aynı işlemi default argument ve named argument nedir bunları öğrenerek yapalım.

Default Argument-Named Argument

Fonksiyon tanımlarken parametreye = operatörü ile bir değer atama işlemine default argument denir. Bu sayede fonksiyonumuzu çağırırken default değere sahip parametrelere değer atamak zorunda kalmayız çünkü default değeri olan parametreler opsiyonel parametrelerdir. Javadan farklı olarak kotlinin bu özelliği sayesinde tekrar tekrar aynı fonksiyonun farklı varyasyonlarını yazmak yerine default değer atayarak overload işlemini gerçekleştirebiliriz.

Default değer atadığımız bir fonksiyonu çağırırken ise devreye named argument girer. Fonksiyonu çağırırken default değeri olan parametreye bir değer atamadığımızda parametre sırası değişebilir. Bu yüzden IDEye hangi parametreye değer atadığımızı belirtmemiz gerekir. Bu işleme de named argument denir. Yukarıdaki örnekle aynı olan aşağıdaki örnekte lesson ve isSuccess parametrelerine default değer atadık(Default Argument). Fonksiyonu çağırma esnasında ise ikinci çağrımda IDE bir hata verdi çünkü isSuccess parametresinden önce lesson parametresi bulunuyordu ki biz buna değer atamadık. Atadığımız değerin lesson parametresine değil de isSuccess parametresine ait olduğunu belirterek bu hatayı gidermiş olduk(Named Argument).

Şimdi tüm parametreleri default olan bir başka örnekle daha açık görelim. Aşağıdaki örnekte fonksiyonumuzun bütün parametrelerine default bir değer atadık. Bu sayede birinci satırda hiç parametre göndermeden, ikinci satırda ilk sıradaki parametreye değer atayarak çağırabildik. Üçüncü satırda ise ikinci sıradaki bir parametreye değer atadığımız için named argument kullandık.(Eğer kullanmasaydık IDE ilk parametre olan number parametresine bu değeri atamaya çalışacak ve bizim verdiğimiz değer string tipinde, parametre ise int tipinde olduğu için hata verecekti.) Fonksiyon çağırdığımız beşinci satırda ise tüm parametrelere değer atadığımız için named argument’e gerek kalmadı ama dilersek yine kullanabiliriz(Altıncı satır).

Variable Number Of Arguments (Değişken Argüman Sayısı)

Şimdiye kadar tanımladığımız fonksiyonlarda parametre sayısı belliydi. Peki ya biz kaç parametre geleceğini bilmiyorsak ne yapacağız?

Bu durumda ise devreye vararg( Variable Number Of Arguments) giriyor. Fonksiyon tanımlarken parametre başına vararg eklediğimizde fonksiyon tek bir parametre alıyor gibi görünür fakat birden fazla parametre atayabiliriz. Aşağıdaki örnekte fonksiyona baktığımızda tek parametreye sahip ama vararg ile tanımladığımız için fonksiyonu çağırdığımızda farklı sayıda değerler atayarak fonksiyonu kullanabildik.

Bir fonksiyona birden fazla vararg ile parametre tanımlayamayız bu durumda aklınıza örnekteki gibi sadece bir tipte mi tanımlamak zorundayım diye gelebilir. vararg parametresinden önce veya sonra farklı tipte parametre tanımlayabiliriz. Burada dikkat edilmesi gereken farklı tipteki parametrelerle tanımlanırken vararg parametresinin son sırada olmasıdır. Son sırada olduğunda JVM’e hazırlanırken Java dilinde olduğu gibi hazırlanır(String… gibi). İlk sırada veya ortalarda olursa JVM’e hazırlanırken bir dizi gibi(String[]) tanımlanır. Bu da performans farkı oluşturacaktır.

Hem vararg şeklinde hem de farklı tipte parametresi olan bir fonksiyonu çağırırken named argument kullanılmalıdır. Çünkü vararg parametresine kaç tane değişken atanacağı belli değildir. Bu yüzden IDE farklı tipteki değişkenin hangi sırada olduğunu anlayamayacaktır.

Single- Expression Kullanımı

Kontrol yapılarında bahsettiğimiz state ve expression kullanımını fonksiyonlar için de geçerlidir. Şimdiye kadar fonksiyonları state olarak kullandık. Eğer fonksiyonumuz tek bir satırdan oluşuyorsa parantezleri kullanmadan expression olarak kullanımına single-expression kullanımı denir ve şu şekildedir:

infix Methodu

Eğer bir fonksiyon bir classın altında tanımlanıyorsa buna method ismi verilir.

  • Daha okunaklı kodlar yazmak için kullanılır.
  • infix keywordü ile başlar.
  • Bir sınıfa ait fonksiyon olmalıdır ya da bir extension fonksiyon(Fonksiyonlar-2 de anlatılacak.) olmalıdır.
  • Sadece bir parametre almalıdır ve bu parametre vararg olamaz.
  • Parametresi default değer alamaz.

Aşağıdaki örnek class içerisindeki fonksiyonun normal kullanımıyla infix kullanımına örnektir.(Bir sonraki konumuz classlar olacaktir :) )

Ayrıca if caselerinde && -|| gibi operatörler yerine and, or gibi ifadeler kullanabiliriz. Çünkü bu keywordler de birer infix methodudur. Biz if içerisinde mantıksal operatör kullanmak yerine infix methodunu çağırmış oluruz.

and-or-xor infix method

Infix methodunun bir classa ait olması gerektiğini söylemiştik. Bu sebepten infix methodu class içinde çağırıyorsak ya normal method çağırımı gibi ya da this kullanımı ile çağırabiliriz. Class dışından ulaşmak istediğimizde ise yukarıda belirttiğimiz gibi classın nesnesi-infix method ismi-parametre şeklinde kullanıyoruz.

Functions Scope(Fonksiyon Kapsamı)

Fonksiyonda { } ile belirttiğimiz, işlem yaptırdığımız alanlardır.

Top-level fonksiyon, Kotlin paketinin içerisindeki herhangi bir sınıf, nesne veya interface dışında tanımlanan fonksiyonlardır. Bu şekilde fonksiyon tanımlandığında herhangi bir nesne veya sınıfı çağırmadan doğrudan fonksiyonu çağırabiliriz. Yazımın başındaki fonksiyon tanımı ve çağırımı görseli bu fonksiyon çeşidine örnek olarak gösterilebilir.

Top-level olarak tanımlanan fonksiyonlara fonksiyon diyebilirken infix method gibi classın üyesi şeklinde tanımlanan fonksiyonlara method denir.

Javadan farklı olarak kotlinde fonksiyon içerisine fonksiyon tanımlayabiliriz. Bu tanımlanan fonksiyonlara da lokal fonksiyonlar denir. Bu şekilde fonksiyon tanımlamamızın amacı; tanımladığımız fonksiyonun kendi sınıfı içerisinde dahi kullanılmasını önleme, bu fonksiyonun başka bir fonksiyon veya sınıf için değiştirilmesini önleme veya reflection(classın,degişkenlerin ve methodların isimleri biliniyorsa çağırılma yöntemi) ile fonksiyonlarımıza erişilirken gizli kalmasını istemek gibi sebepler söylenebilir.

Top-level fonksiyon tanımladığımızda tanımlanan alandan önce veya sonra bu fonksiyonu çağırabilirken, lokal fonksiyon tanımlandığı alanın altında ve içerisinde bulunduğu üye fonksiyonun alanında kullanılabilir.

Extension ve Higher Order fonksiyonlar yazısında görüşmek üzere iyi çalışmalar…. :)

--

--