Swift ve OOP: Bazı Başlıklar

Herkese selam,

İlk yazımda kod ekranıyla bir kere de olsa bakışmış birinin az çok aşina olduğu bir konudan bahsetmek istedim; Object Oriented Programming, Nam-ı diğer Nesne Tabanlı Programlama.

Web'te ufak bir search ile gırla sonuca ulaşabildiğimiz veya tek bir yapay zeka promptu ile fazlasıyla aydınlanacağımız bu konuyla alakalı içerik oluşturma sebebim hem kendi üslubumca anlatmak hem de tekrar niteliğinde kendime hatırlatma yapmak diyebilirim.

OOP pek çok modern dil gibi Swift'in de omurgasını oluşturmakta. OOP olmadan swift olmazdı diyebiliriz.

O zaman başlayalım;

Class Yapısı

Classları belirli nesneleri, öğeleri veya canlı parçaları bulunan gerçek bir dünya grubu gibi düşünebiliriz. Bu gruba mensup çeşitli özellik ve davranışlara sahip öğeleri de objeler olarak düşünebiliriz.

class Kahve {
    // Aşağıdaki gibi özellikler ekleyebiliriz.
    var tur:String? 

}

Objects

Bir sınıftan meydana gelen herhangi bir şeydir. Kedi, köpek, kalem vs. Yukarıdaki örnekten devam edecek olursak örneğin Latte kahve sınıfına ait bir nesnedir. Latte tür olarak ise espresso bazlıdır.

var Latte = Kahve()
latte.tur = "Espresso Bazlı"
print(latte.tur!) // konsol çıktısı "Espresso Bazlı" olacaktır.

Properties

Properties bir sınıfın özellikleri diyebiliriz. Yukarıdaki lattenin türü şeklinde belirttiğimiz gibi.

class Kahve {
    // Aşağıdaki gibi özellikler ekleyebiliriz.
    var tur:String? 
    var icim:String?

var Latte = Kahve()
latte.tur = "Espresso Bazlı"
latte.icim = "Sıcak ve soguk icilebilir."

}

Inheritance

Türkçe kaynaklarda kalıtım olarak da rastlanılabilir. Adından da anlaşılacağı üzere bir sınıfın alt sınıfı diyebiliriz.

class SogukKahve:Kahve {
}

let coldBrew = SogukKahve()
coldBrew.tur = "Filtre Kahve Bazlı"

Ne yaptık:

1- Soğuk kahveyi kahve sınıfının mirası olarak gösterdik yani inheritance yapmış olduk.

2- coldBrew nesnesi SoğukKahve sınıfına bağlı olduğu halde kalıtım içerdiği için superclassın yani Kahve sınıfının propertiesini(coldBrew.tur) kullanmış oldu.

Method Overriding

Kısaca özetlemek gerekirse alt sınıfın içerisinde bulunan fonksiyonun kendine has bir şekilde davranması diyebiliriz.

class Kahve{
func demlen(){
    print("demlendi")
}
}
class FiltreKahve:Kahve{
    override func demlen(){
    print("siparişe hazır")
}
}

Ne yaptık:

Kalıtım yoluyla aktarılmış bir sınıf fonksiyonunun override ile farklı bir şekilde işledik.

Polymorphism

En soyut kavramlardan bir tanesidir. Çok biçimlilik diye de geçer.

Object Oriented Programming yaklaşımında, bir class'a ait olan bir metot inherit edilmis subclass tarafindan kullanılacagi vakit parent class'taki metodu override ederek uygulanan mantığı o subclass çapında değiştirmesine denir.

class Kahve{
    func demlen(){
    print("demlendi")
}
}
class FiltreKahve:Kahve{
     func demlen(){
    print("siparişe hazır")
}

let Jacobs:Kahve = FiltreKahve()

Ne Yaptık:

Jacobs değişkeni kahve türünde olsa da daha kapsayıcı şekilde davranmak için FiltreKahve sınıfına ait oldu.

Type Casting

Swift programlama dili farklı türdeki verileri tutabilmek için tipleri kullanır. Tiplere örnek olarak:

String
Int
Bool

Oluşturacağımız her değişken için tip belirtmek zorunda değiliz. Bazen tip atamasak da otomatik olarak belirlenmektedir.

var isim:String = "Ali"

Yukarıda isim değişkeninin türünü String olarak belirtmemiş olsaydık da derleyici tarafından otomatik olarak atanacaktı.

Type casting ise bir türü başka bir tür gibi davranmaya zorlamaktır. Upcasting ve downcasting olarak ikiye ayrılmaktadır.

Upcasting

Bir nesnenin kalıtımını aldığı superclass'a dönüşmesidir. Yani subclass'tan superclass'a dönüştürmektir.

Downcasting

Downcasting ise upcastingin tam tam tersidir diyebiliriz. Superclass'ın subclass'a dönüştürülmesidir. Force downcasting yapılırken as! kullanırken conditional casting yapılırken as? ifadesi kullanılır.

Extension

Varolan sınıflarımızı genişletmek için kullanırız. Kodlarınızı daha düzenli halde tutmak yani temiz bir kod için kullanabiliriz.

class Motosiklet {
     var marka:String
     var uretimSenesi:Int

     init(marka:String, uretimSenesi:Int)
            self.marka = marka
            self.uretimSenesi = uretimSenesi
}
extension Motosiklet { 
    func bilgiVer{
        print("\(marka) marka motosiklet ilk olarak \(uretimSenesi) yılında üretilmiştir.")
}
}

init” methodu sınıfımızda bulunan her bir değişken için bir başlangıç ​​değeri ayarlamayı sağlar.

Şimdi bir adet Motosiklet sınıfına ait değişken tanımlayalım.


var ducatiMonster = Motosiklet(marka:"Ducati Monster", uretimSenesi = 2010)
ducatiMonster.bilgiVer()

Değişkenimizi de tanımladık. Konsol çıktımız ise aşağıdaki gibi olacak.

// "Ducati Monster marka motosiklet ilk olarak 2010 yılında üretilmiştir."

Evet bu kadar. Kafamızda hemen bir soru belirmiş olabilir. Bu fonksiyonu sorunsuz bir şekilde classın içerisinde de yazabilirdik neden özellikle extensionla belirttik? Bu sorunun cevabı temiz ve daha düzenli kod yazmak olacaktır. Binlerce fonksiyonun bulunduğu bir class görünümü çok okunabilir olmayacak ve rahatsız edici olaraktır.

Protocols

Protokollere belirli bir class, struct ve enum sınıfına eklenebilen ve eklendiğinde içerdiği fonksiyonları kullanma zorunluluğu kılan bir iletişim kuralı diyebiliriz. Swift dili çoklu miras özelliği desteklememekte ancak çoklu protokolu desteklemektedir. Yani bir sınıfa birden fazla protokol atanabilir.

protocol Motosiklet {
}
protocol Naked {
}
class DucatiMonster:Motosiklet, Naked {
}

Yukarıda oluşturduğumuz DucatiMonster classına iki adet swift protokolü eklemiş bulunduk. Şimdi protokollerimize biraz fonksiyon ekleyelim.

protocol Motosiklet {
    var ikiTekerMi:Bool
    func yolculukEt(){
}
}

Yukarıda protokolümüze ikiTekerMi adında bir değişken ve yolculukEt adında bir fonksiyon ekledik. Fonksiyonun içini boş bırakmış olsak da daha sonra class veya struct içerisinde gövdesine ekleme yapabiliriz.

class Yamaha:Motosiklet{
    var ikiTekerMi:Bool {get}
    func yolculukEt(){
        print("Yamaha yolculuk ediyor.")
}
}
let yamahaR25 = Yamaha()

yamahaR25.yolculukEt()
// "Yamaha yolculuk ediyor"

Konsol çıktımız bu şekilde olacaktır.

Closures

Closure konusu swift programlama dilinde önemli yer tutmaktadır. Closures'i kısaca açıklamak gerekirse fonksiyonların kısa hali diyebiliriz. Closure'ı basitçe anlatmak için pek çok kaynak toplama işlemi üzerinden ilerlemiş, biz de öyle yapalım :)

func toplama(sayi1:Int, sayi2:Int) -> Int {
    return sayi1 + sayi2
}
var topla = toplama(20+10)
print(topla)
// 30

bu fonksiyonu closure olarak yazmak istersek;

var topla = { (sayi1:Int, sayi2:Int) -> Int in
    return sayi1 + sayi2
}
topla(20+10)
print(topla)
// 30