Kotlin'de soyut sınıflar (abstract class) ve arayüzler (interface), soyut bir mantığı tanımlamak için kullanılır, ancak aralarında önemli farklar bulunmaktadır:
abstract class Animal(val name: String) { abstract fun makeSound() fun info() = println("Ben $name") } interface Movable { fun move() } class Cat(name: String) : Animal(name), Movable { override fun makeSound() = println("Miyav") override fun move() = println("Kedi hareket ediyor") }
Kotlin'de bir arayüz durumları (backing field) içerebilir mi?
Çoğu kişi arayüzde özelliklerin tanımlanabileceğini söyler, ancak bunlar yine de backing field'a sahip olamaz — yalnızca değer saklamayan getter/setter'lar vardır. get() = ... yazsanız bile — değer her seferinde hesaplanır.
Örnek:
interface MyInterface { val value: Int get() = 42 // değer saklamaz, anlık hesaplama }
Hikaye
Büyük bir projede, kıdemli bir geliştirici arayüzde bir durum saklamaya (örneğin, sayacı) çalışıyordu ve var count: Int özelliğinin backing field'a sahip olmasını umuyordu. Sonuçta, arayüzü uygulayan tüm sınıfların değeri farklı şekillerde saklaması gerekti, bu da kararsız bir mantığa yol açtı (değer saklamak için setter'ı yeniden tanımlamayı unuttuklarında veriler kayboluyordu).
Hikaye
Bir geliştirici, çeşitli davranış stratejilerinin çoklu uygulamasının gerekli olduğu yerde soyut sınıf kullandı (strateji modeli). Sonuç olarak bir sorun ortaya çıktı: yalnızca bir temel sınıf hiyerarşisi vardı, ancak farklı davranış yönleri için kompozisyon gerekiyordu. Mimarinin arayüzlere göre değiştirilmesi gerekti.
Hikaye
Ekip, iki soyut sınıfı (biri mantık, diğeri ortak yardımcılar içeren) aynı anda miras almaya çalıştı, bu Kotlin'de mümkün değil. Sorun, uygulamanın genişletme aşamasında ortaya çıktı. Bu durum, sınıfların acil olarak yeniden düzenlenmesi gerektiği için önemli bir teknik borç doğurdu.