Genişletme fonksiyonları (extension functions), Kotlin'in Java'dan en önemli farklarından biridir ve C#'tan esinlenerek dilin ilk sürümleriyle birlikte ortaya çıkmıştır. Mevcut sınıflara (örneğin, String veya List) yeni yöntemler eklemeyi sağlar, miras alma veya kaynak sınıfı değiştirme ihtiyacı olmadan. Bu, kodun ifade gücünü ve kısalığını önemli ölçüde artırır.
Java ve birçok diğer dilde, mevcut bir sınıfa (örneğin, String veya List) yöntem eklemek mümkün değildir, bu genellikle miras alma veya Decorator deseninin kullanımıyla yapılır. Kotlin, bu eksikliği genişletme fonksiyonları mekanizmasıyla çözer.
Kütüphanedeki birçok sınıf (örneğin, String, Int, List) doğrudan değiştirilemez. Kodun daha okunaklı olmasını sağlamak ve mantığın tekrarlanmasını önlemek için ek yöntemlere sıkça ihtiyaç duyulur. Ancak, genişletme fonksiyonları gerçek sınıfı değiştirmez — bunlar statik olarak oluşturulur ve içinde private/protected üyelere erişim yoktur.
Kotlin'de, bir genişletme fonksiyonun bildirimi şu şekilde görünür:
fun String.lastChar(): Char = this[this.length - 1]
Artık bu yöntemi herhangi bir String üzerinde çağırabilirsiniz:
"Kotlin".lastChar() // 'n' döndürecek
Bir genişletme fonksiyonu bir sınıfın alt sınıfında geçersiz kılınabilir mi?
Hayır. Genişletme fonksiyonları sınıfın üyeleri değildir, override ile geçersiz kılınamaz: statikliği, miras alanlar için bile kendini gösterir — derleyici, ifadelerin tipine göre fonksiyonu seçer, nesnenin gerçek tipine göre değil.
open class Base class Derived : Base() fun Base.foo() = "base" fun Derived.foo() = "derived" fun printFoo(b: Base) { println(b.foo()) } val d = Derived() printFoo(d) // "base" yazdırır
Genişletme fonksiyonları nesnenin durumunu değiştirebilir mi?
Genişletme fonksiyonları private/protected duruma erişme imkanı bulamaz, ancak eğer tip mutable ise (örneğin, List veya kendi sınıfınız), kamu yöntemleri aracılığıyla erişilebilir dış durumu değiştirebilirler.
fun MutableList<Int>.addTwice(elem: Int) { add(elem) add(elem) }
Genişletme fonksiyonları, aynı isimdeki sınıf üyeleri ile çakışır mı?
Eğer genişletme adı, gerçek bir yöntem adı ile çakışıyorsa, öncelik sınıf üyesine aittir. Genişletme yalnızca üyelerin mevcut olmadığı veya görünmediği durumda çağrılacaktır.
class Foo { fun bar() = "member" } fun Foo.bar() = "extension" val f = Foo() println(f.bar()) // "member"
Bir geliştirici, standart String'e projeye özgü bir format belirleyen bir fonksiyon genişletir ve bunu her yerde kullanır — diğer geliştiriciler ise bu işlemin standart String sınıfının bir işlemi olmadığını fark etmez.
Artılar:
Eksiler:
Standart sınıfı, utils paketinde net bir şekilde yerleşik ve iyi belgelenmiş bir yardımcı yöntemle genişletmek. Kullanım, kesin bir şekilde belirlenen kod bölümleriyle sınırlıdır.
Artılar:
Eksiler: