Kotlin SAM Dönüşümü ile Temiz ve Etkili Kod Yazımı


Görsel Referansı



1. SAM / Fonksiyonel Arayüz


Yalnızca tek bir soyut metot içeren arayüzler, fonksiyonel interface ya da SAM (Single Abstract Method) interface olarak adlandırılır.


Kotlin'de SAM interface tanımlamak için fun keyword'u kullanılır. Tek soyut metot içeren bir SAM arayüzünü aşağıdaki gibi tanımlayabiliriz.




2. SAM Dönüşümü


Fonksiyonel arayüzler için lambda ifadesi kullanarak kodunuzu daha kısa ve okunabilir hale getirmeye yardımcı olan SAM dönüşümünü kullanabilirsiniz. Bu dönüşüm sadece fonksiyonel arayüzler için geçerlidir. Birden fazla soyut metot içeren bir interface ya da tek soyut metoda sahip soyut bir sınıfımız olsa dahi SAM dönüşümünde kullanamayız.


SAM dönüşümü olmadan manuel olarak sınıf oluşturup arayüzü implement etmemiz gerekir. Bu şekilde aşağıdaki gibi bir kullanım, kısa ve öz olmaktan oldukça uzaktır.



SAM dönüşümü ile aynı yapıyı lambda ifadesi kullanarak çok daha kısa ve anlaşılır bir şekilde aşağıdaki gibi yazabiliriz. Ayrıca Kotlin'de yazdığımız bu lambda ifadesi, Java arayüzleri ile de çalışabilir durumdadır.



Görüldüğü gibi anonim sınıf, arayüz adının önüne eklenen kısa bir lambda ifadesiyle değiştirildi. Burada lambda ifadesinin aldığı bağımsız değişken sayısının arayüzde bulunan metot imzasındaki parametre sayısına eşit olduğunu vurgulamak gerekir.



3. "it" Değişkeni


Çoğunlukla, SAM arayüzleri tek parametreli metotlar içerir. Adından da anlaşılacağı gibi tek parametreli bir metodun imzasında yalnızca bir parametre vardır. Bu tür arayüzlerle çalışırken Kotlin, lambda ifadenizin imzasındaki parametreyi çıkarmanıza ve ifadenin gövdesinde 'it' adı verilen bir değişken kullanmanıza izin verir.


IntPredicate arayüzünü kullanırken, lambda ifadesinin imzasında 'i' parametresinin açıkça belirtilmesi gerekmez. Bunun yerine, ona basitçe 'it' yani 'o' diyebiliriz.




4. Fonksiyon Çağrılarında SAM Dönüşümü


Parametresinde SAM tipinde argüman alan metotlara sahip Java sınıflarıyla çalışırken kod parçacığımızı daha basit hale getirebiliriz. Örneğin Java'da aşağıdaki gibi 'NumberFilter' adlı bir sınıfımız olsun ve bu sınıf 'IntPredicate' arayüzünü implement eden bir obje bekleyen metoda sahip olsun.



Lambda ifadesini, önüne IntPredicate arayüzünü eklemeden direkt olarak setIntPredicate() metoduna aşağıdaki gibi gönderebiliriz. Ayrıca çağrılan metot tek argüman olarak SAM tipi aldığından parantezler kaldırılarak kodun daha da kısaltılması sağlanabilir.




5. Argüman Olarak Fonksiyon ile SAM Dönüşümü


Eğer aşağıdaki gibi IntPredicate SAM arayüzündeki metodun imzası ile eşleşen bir metodunuz varsa bu fonksiyonu '::' operatörünü kullanıp direkt olarak NumberFilter sınıfının setIntPredicate() metoduna lambda ifadesi kullanmadan gönderebilirsiniz.




6. SAM Arayüzü Kullanmadan Yapılan Dönüşüm


Daha önce, Java sınıfımızda argüman olarak SAM Interface alan bir metot ile dönüşüm işlemi gerçekleştirmiştik. Aynı sınıfı Kotlin'de SAM interface implementasyonuna ihtiyaç duymadan aşağıdaki gibi oluşturabiliriz.



Burada, önceki sınıfımızdaki gibi IntPredicate delegasyonunu kullanmadık ve setIntPredicate() gibi bir metoda ihtiyacımız olmadı. Sadece intPredicate fonksiyonu için varsayılan bir implementasyon gerçekleştirdik.


Aşağıdaki şekilde sınıfı kullanırken, önceden tanımladığımız bir fonksiyonu veya o an tanımladığımız ifadeyi atayabiliriz.




7. SAM Dönüşümünün Arka Planı ve Performans


SAM dönüşümünün altyapısını incelediğimizde, Kotlin derleyicisinin aslında hala anonim sınıf oluşturduğunu görebiliriz. Aşağıdaki gibi SAM dönüşümü kullanmadan, object anahtar kelimesini kullanarak Thread örneği oluşturalım.



Bu şekilde bir kullanımda, her Thread objesi oluşturma işleminde tekrardan bir anonim sınıf oluşturulduğu görülür. Öte yandan, SAM dönüşümünü kullandığımızda, Singleton bir Thread örneği oluşturulur ve bu örnek her ihtiyacımız olduğunda yeniden kullanılır. Böylece, SAM dönüşümü kodumuzu kısa ve öz hale getirmesinin yanında, daha az nesne oluşturulmasını sağlayarak avantajlı bir bellek yönetim imkanı verir.


Ancak, SAM dönüşümündeki bu avantajı kaybettiğimiz bir durum mevcut. Eğer sınıf örneği oluştururken aşağıdaki gibi scope dışındaki bir değişkeni kullanırsak, her seferinde yeni bir nesne oluşturulmasına neden oluruz. Bu problemden kaçınmak için Kotlin'deki inline fonksiyonlara göz atabilirsiniz.




8. Sonuç


SAM dönüşümü, Kotlin'deki fonksiyonel arayüzlere ek olarak Java arayüzleri ile de uyumlu bir şekilde çalışabilen bir yapıdır. Birçok farklı kullanım yöntemiyle daha kısa ve anlaşılır kodlar yazılmasına olanak sağlar. Tüm bunlara ek olarak, doğru bir şekilde kullanıldığında performans artışı sağlaması da önemli bir avantajıdır.


Referans ve daha fazla detay için:

https://kotlinlang.org/docs/reference/fun-interfaces.html

https://code.tutsplus.com/tutorials/quick-tip-write-cleaner-code-with-kotlin-sam-conversions--cms-29304

https://www.baeldung.com/kotlin/sam-conversions


#kotlin #android #sam #samconversion #cleancode

0 yorum

Son Paylaşımlar

Hepsini Gör