extension function — Kotlin'in mevcut sınıflara kalıtım olmadan ve kaynak kodu değiştirmeden yeni metotlar eklemeyi sağlayan bir mekanizmasıdır. Fonksiyon, bir alıcı türü öneki ile bildirilir ve bu türün normal bir metodu gibi çağrılır. Kotlin Documentation, 2025'e göre, extension functions, alıcıyı ilk parametre olarak alan statik metotlara derlenir ve normal çağrılara kıyasla çalışma zamanında sıfır overhead garanti eder.
Önemli Noktalar
Extension function, bir sınıfın dışında bildirilen ancak onun metodu olarak çağrılan bir fonksiyondur. Yeni metodun ekleneceği bir alıcı türü alır. Fonksiyonun içinde, this anahtar sözcüğü alıcı türünün örneğini ifade eder. Bu yaklaşım, final sınıfları, üçüncü taraf kütüphane sınıflarını ve hatta ilkel türleri sarmalayıcı oluşturmadan genişletmeye olanak tanır.
Java'nın aksine, mevcut bir sınıfa metot eklemek için kalıtım veya statik bir yardımcı sınıf gerekirken, Kotlin boilerplate olmadan zarif bir çözüm sunar. Kotlin Foundation araştırmasına (2024) göre, extension functions dilin en çok kullanılan ilk beş özelliği arasındadır — Kotlin geliştiricilerinin %78'i bunları günlük işlerinde kullanmaktadır.
Kotlin derleyicisi, extension function'ı alıcı örneğinin ilk argüman olarak iletildiği statik bir metoda dönüştürür. Bu, extension functions'ın hedef sınıfın bayt kodunu değiştirmediği ve kapsüllemeyi bozmadığı anlamına gelir — yalnızca alıcının genel alanlarına ve metotlarına erişilebilir.
Belirli bir türe mantıksal olarak bağlı olan ancak kaynak koduna eklenemeyen temiz yardımcı fonksiyonlar yazmak için extension functions kullanın.
Bir extension function'ın temel sözdizimi: alıcı türü adı, bir nokta, fonksiyon adı, ardından parametreler ve dönüş türü. Fonksiyonun içinde, alıcıya this aracılığıyla erişilebilir.
// Extension function for String
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Called as regular String method
val result = "user@example.com".isEmail() // true
Bu örnekte, isEmail() tüm dizeler için kullanılabilir hale gelir. Fonksiyonun içinde this, metodun çağrıldığı dizenin kendisini ifade eder. Kotlin çoğu durumda this'in atlanmasına izin verir — this.contains("@") yerine sadece contains("@") yazabilirsiniz.
Extension functions ek parametreler alabilir ve herhangi bir türde değer döndürebilir. Bu, onları yalnızca sözdizimsel şeker değil, tam teşekküllü fonksiyonlar yapar.
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
if (this.isEmpty()) return listOf(default)
return this
}
val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)
default parametresi, boş bir liste için döndürülecek değeri tanımlar. Bir extension function generic olabilir — List
Kotlin'deki extension functions statik dağıtım kullanır, sanal dağıtım kullanmaz. Bu, normal sınıf metotlarından önemli bir farktır. Hangi extension function'ın çağrılacağı, çalışma zamanı türüne göre değil, değişkenin statik türü tarafından derleme zamanında belirlenir.
open class Animal
class Dog : Animal()
fun Animal.speak() = "Animal sound"
fun Dog.speak() = "Woof"
fun test() {
val animal: Animal = Dog()
println(animal.speak()) // "Animal sound" — static type Animal
val dog: Dog = Dog()
println(dog.speak()) // "Woof" — static type Dog
}
animal değişkeni Dog örneğini gösterse bile, değişkenin statik türü Animal olduğu için Animal için extension function çağrılır. speak() sanal bir sınıf metodu olsaydı, Dog.speak() çağrılırdı. Bu davranış, extension functions ile API tasarlarken dikkate alınması önemlidir.
Extension functions sınıf üyesi değildir — başka bir dosyada kullanılmak için import gerektiren normal fonksiyonlardır. Kotlin iki import seçeneği sunar: fonksiyon adına göre veya yeniden adlandırarak.
// Import by name
import com.example.extensions.isEmail
// Import with alias (to resolve conflicts)
import com.example.extensions.isEmail as isValidEmail
// Call after import
val valid = "test@test.com".isEmail()
as ile yeniden adlandırma, ad çakışmalarında kullanışlıdır — örneğin, iki kütüphane aynı tür için aynı ada sahip bir extension function sağlıyorsa. Bu durumda, bunlardan birini farklı bir adla import edebilir ve yeni adı kullanarak çağırabilirsiniz.
Extension functions farklı seviyelerde bildirilebilir:
| Seviye | Görünürlük | Örnek |
|---|---|---|
| Top-level | Import sonrası tüm proje | fun String.isEmail() |
| Member extension | Sahip sınıfın içinde | class A { fun B.ext() } |
| Local | Bir fonksiyonun içinde | fun test() { fun String.ext() } |
Member extension functions, extension function'ın başka bir sınıfın içinde bildirildiği özel bir durumdur. Bu durumda, extension function'ın içinde hem alıcıya (fonksiyonun this'i) hem de dış sınıfın üyelerine erişilebilir.
Bir sınıfın, bir extension function ile aynı imzaya sahip bir metodu varsa, her zaman sınıf üyesi çağrılır. Bir extension function asla bir sınıf metodunu geçersiz kılmaz — bu, kazara geçersiz kılmaları önlemek için bir mimari karardır.
class User {
fun greet() = "Hello from class"
}
fun User.greet() = "Hello from extension"
fun main() {
val user = User()
println(user.greet()) // "Hello from class"
}
Extension function daha sonra tanımlanmış ve aynı imzaya sahip olsa bile, derleyici sınıf metodunu seçecektir. Kotlin derleyicisi bu durumu tespit ettiğinde bir uyarı verir. Bir sınıf metodu varken extension function'ı çağırmanın tek yolu, onu normal bir fonksiyon olarak çağırmaktır: greet(user).
Android geliştirmede, extension functions View, Context ve fragmentlerle çalışmak için standart bir araç haline gelmiştir. Android KTX kütüphanesi, extension functions üzerine inşa edilmiştir ve Android API'si üzerinde kullanışlı sarmalayıcılar sağlar.
// Extension function for working with View
fun View.show() {
visibility = View.VISIBLE
}
fun View.hide() {
visibility = View.GONE
}
// Extension function for Context — toast
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
// Extension function as DSL builder
fun String.colorFormat(color: String): String =
"$color$this\u001b[0m"
toast() extension function, Context'e bağlı çağrıları kısa ve öz hale getirir: Toast.makeText(context, message, length).show() yazmak yerine, sadece context.toast("Metin") yazmak yeterlidir. Bu, boilerplate'i azaltır ve kodu daha okunabilir kılar.
Sıkça Sorulan Sorular
Hayır, extension functions statik dağıtım kullanır. Bir temel sınıf ve bir alt sınıf için aynı extension function'ı bildirirseniz, hangisinin çağrılacağı, gerçek çalışma zamanı türüne göre değil, derleme zamanında değişkenin statik türü tarafından belirlenir.
Nullable alıcı türleri için extension functions bildirebilirsiniz: fun String?.isNullOrEmail(). Böyle bir fonksiyonun içinde this null olabilir, bu nedenle güvenli çağrı operatörleri veya açık null kontrolleri kullanmalısınız.
Hayır, extension functions statik metotlara derlenir. Bayt kodu seviyesinde, bir extension function'ı çağırmak, alıcıyı ilk parametre olarak alan statik bir metodu çağırmakla aynıdır. Herhangi bir yansıma veya dinamik dağıtım söz konusu değildir.
Evet, extension properties, extension functions'a benzer şekilde çalışır ancak durum depolayamaz — yalnızca getter ve setter. Örneğin: val List
Java'da StringUtils.isEmail(str) yazarken, Kotlin'de str.isEmail() yazarsınız. Fark sadece sözdiziminde değil: extension functions IDE'de otomatik tamamlamayı destekler, çağrı zincirlerinin okunabilirliğini artırır ve IDE'nin belirli bir tür için ilgili fonksiyonlar önermesine olanak tanır. Java bu yeteneklere sahip değildir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun