← Ana Sayfaya Dön

Kotlin'de Sınıflara ve OOP

Kategori: Kotlin10 Ocak 2025

Sınıf Tanımlama

Kotlin'de bir sınıf tanımlamak için class anahtar kelimesi kullanılır:

class Person { var name: String = "" var age: Int = 0 }

Görüleceği üzere Person sınıfı içinde name ve age değişkenleri tanımlanmıştır.

Person sınıfından tanımlanan nesnelerin name ve age değişkenleri olur ve bu değişkenlerin değeri her nesne için farklı belirlenebilir.

Person sınıfından nesne oluşturmak için:

val person = Person() person.name = "Bilocan" person.age = 22

Abstract Class

Abstract class'lar, sınıfların genel özelliklerini ve davranışlarını tanımlamak için kullanılır.

Kendileri başlı başına bir nesne oluşturamaz, alt sınıflar için temel işlevsellik ve özellikler sunar. İçinde hem somut (tamamlanmış) hem de soyut (tamamlanmamış, override edilmesi gereken) metodlar bulunabilir.

abstract class Hayvan { abstract fun sesCikar() // Soyut metod, alt sınıfta override edilmeli fun hareketEt() { // Somut metod println("Hareket ediyorum!") } } class Kedi : Hayvan() { override fun sesCikar() { println("Miyav!") } } fun main() { val kedi = Kedi() kedi.sesCikar() // Çıktı: Miyav! kedi.hareketEt() // Çıktı: Hareket ediyorum! }

Interface

Interface'ler bir sınıf değildir fakat sınıfların belirli davranışlarını zorunlu kılmak için kullanılır.

Tüm metodları varsayılan olarak soyuttur ve override edilmelidir. Ancak, Kotlin'de default bir implementasyon (varsayılan metodlar) da tanımlanabilir.

Bir sınıf birden fazla interface'i implement edebilir.

interface Ucan { fun uc() // Soyut metod } interface Yuzebilen { fun yuz() { // Varsayılan metod println("Suda yüzüyorum!") } } class Marti : Ucan, Yuzebilen { override fun uc() { println("Gökyüzünde uçuyorum!") } } fun main() { val marti = Marti() marti.uc() // Çıktı: Gökyüzünde uçuyorum! marti.yuz() // Çıktı: Suda yüzüyorum! }

Constructor

Kotlin'de birincil (primary) ve ikincil (secondary) constructor'lar bulunur:

Primary Constructor

class SuperKahraman(val isim: String, var yas: Int, var meslek: String) { }

Primary constructor bu şekilde tanımlanır, daha basit ve temiz bir yapıdır.

Secondary Constructor

class SuperKahraman { var isim = "" var yas =0 var meslek ="" constructor(isim:String, yas: Int, meslek: String){ this.yas=yas this.meslek=meslek this.isim=isim } }

Bu şekilde tanımlanan constructor'a secondary constructor denir. Bu yapı da kabul edilebilir ama primary constructor'dan daha karmaşık ve uğraştırıcıdır.

Bu yüzden primary constructor kullanılır.

Kalıtım (Inheritance)

Kotlin'de kalıtım için : operatörü kullanılır:

open class Animal { open fun makeSound() { println("Animal sound") } } class Dog : Animal() { override fun makeSound() { println("Woof!") } }

Verilen örnekte Animal sınıfından kalıtım alan Dog sınıfında makeSound fonksiyonu override edilerek Dog sınıfının içinde kendisine göre çalıştırılmıştır.

Not: open anahtar kelimesi ile ana sınıftaki fonksiyonların override edilebilir olması sağlanır.

Kapsülleme (Encapsulation)

Kapsülleme sınıf içerisindeki verilerin sadece izin verildiği derecede erişebilir olmasını sağlar.

class Kisi { // Erişilemeyen özel değişken (private) private var sifre: String = "ruhi123" // Erişilebilen genel değişken (public) var ad: String = "Bilinmeyen Kişi" // Getter ve Setter metotları (şifreye erişim için) fun setSifre(yeniSifre: String) { sifre = yeniSifre } fun getSifre(): String { return sifre } }

Şimdi bu sınıfın içinden kapsülleme'yi kullanmak için:

fun main() { val kisi = Kisi() // Erişilebilen değişken kisi.ad = "Ayşe" println("Ad: {kisi.ad}") // Erişilemeyen değişken // println(kisi.sifre) // HATA: 'sifre' özelliği private olduğu için erişilemez. // Şifreye erişim için metotlar kullanılmalı println("Şifre: {kisi.getSifre()}") // Getter metodu ile erişim kisi.setSifre("ruhicenet123") // Setter metodu ile yeni değer atama println("Yeni Şifre: {kisi.getSifre()}") } //Süslü parantezlerden önce gelmesi gereken $ işareti formatın bozulmaması için silinmiştir.

Erişilebilen Değişken:

  • ad değişkeni public olduğu için doğrudan erişilebilir.
  • kisi.ad = "Ayşe" satırı ile değer atanabilir ve println(kisi.ad) ile okunabilir.

Erişilemeyen Değişken:

  • sifre değişkeni private olduğu için doğrudan erişilemez. println(kisi.sifre) yazmaya çalıştığında hata alırsın.
  • Şifreye sadece setSifre ve getSifre metotlarıyla erişim sağlanabilir.

Visibility Modifiers

  • public: Varsayılan erişim seviyesidir; her yerden erişilebilir.
  • private: Yalnızca tanımlandığı sınıf içinde erişilebilir. Dışarıdan erişime kapalıdır.
  • protected: Yalnızca tanımlandığı sınıf ve bu sınıftan türetilen alt sınıflarda erişilebilir.
  • internal: Aynı modül içerisindeki tüm dosyalardan erişilebilir, modül dışına kapalıdır.

Çok Biçimlilik (Polymorphism)

Kotlin'de iki tür çok biçimlilik vardır, Static Polymorphism ve Dynamic Polymorphism.

Static Polymorphism, compile time'da belirlenir.

open class Islemler { // Statik Polymorphism: Method Overloading fun toplama(x: Int, y: Int): Int { return x + y } fun toplama(x: Int, y: Int, z: Int): Int { return x + y + z } fun toplama(x: Int, y: Int, z: Int, k: Int): Int { return x + y + z + k } // Dinamik Polymorphism: Method Overriding yapma işlemi open fun carpma(x: Int, y: Int): Int { println("Islemler sınıfındaki carpma fonksiyonu çalıştı") return x * y } }

Şimdi bu sınıfın içinden statik polymorphism'ı kullanmak için:

val islem = Islemler() islem.toplama(1,2) islem.toplama(1,2,3) islem.toplama(1,2,3,4)

Dinamik Polymorphism

Dinamik polymorphism, runtime'da belirlenir. Dinamik polymorphism'de inheritance yapısı kullanılır.

Aynı işlemler sınıfını kullanarak dinamik polymorphism'ı kullanmak için:

class GelişmişIslemler : Islemler() { // carpma metodu override edildi override fun carpma(x: Int, y: Int): Int { println("GelişmişIslemler sınıfındaki carpma fonksiyonu çalıştı") return (x * y) * 2 // Örneğin: Sonuç iki katına çıkarıldı } }

Şimdi bu sınıfın içinden dinamik polymorphism'ı kullanmak için:

val gelişmişIslemler = GelişmişIslemler() gelişmişIslemler.carpma(1,2)

Özet

  • Bir sınıf yalnızca bir adet abstract sınıfı miras alabilir. Ancak bir sınıf birden fazla interface'i implement edebilir.
  • Kotlin'de sınıflar, nesneleri modellemek için kullanılır ve class anahtar kelimesiyle tanımlanır. Bir sınıf, değişkenler ve fonksiyonlar içerebilir.
  • Primary constructor, sınıfın başında tanımlanır ve temel özelliklerin başlatılmasını sağlar. Secondary constructor ise ek ihtiyaçlar için kullanılabilir ve daha esnek başlatma imkânı sunar.
  • Kotlin'de bir sınıf, başka bir sınıfın özelliklerini ve davranışlarını : ile devralabilir. Bu, kodun yeniden kullanılabilirliğini artırır ve daha düzenli bir yapı sağlar.
  • Kapsülleme, sınıfın içindeki verileri gizleyerek sadece belirli metotlarla erişime izin verir. private, public, internal ve protected gibi erişim belirleyiciler kullanılarak veri kontrol edilir.
  • Çok biçimlilik, aynı metot veya sınıfın farklı şekillerde çalışmasını sağlar. Statik ve dinamik olarak iki türü vardır.