Class, Swift dilinde bir referans türüdür (reference type) ve örnekleri atama sırasında kopyalanmak yerine referans olarak iletilir. Struct'ların aksine, sınıflar kalıtım, sonlandırma ve bellek yönetimi için otomatik referans sayımı ARC'yi destekler. Swift Programming Language Guide, 2026'ya göre, Apple'ın UI çerçeveleriyle (UIKit, AppKit) çalışmak ve nesnenin paylaşılan kimliğini gerektiren desenleri uygulamak için class gereklidir. class ve struct arasındaki seçim, Swift'teki temel mimari kararlardan biridir.
Önemli Noktalar
Class — özellikleri ve yöntemleri kalıtım ve dinamik gönderme desteğiyle tek bir varlıkta gruplayan Swift'teki bileşik referans türüdür. Struct'ın aksine, bir sınıf örneği yığında (heap) oluşturulur ve bir değişken, verinin kendisini değil, bu örneğe bir referans saklar.
Bir sınıf değişkenini başka bir değişkene atadığınızda, her ikisi de bellekteki aynı nesneyi referans alır. Bir referans üzerinden yapılan değişiklikler diğeri üzerinden görünür — bu, referans türlerinin temel bir özelliğidir ve yetkilendirme, gözlem ve paylaşılan durum desenlerinde kullanılır.
Apple Swift Belgeleri'ne göre, tüm UI bileşenlerinin UIView ve UIViewController'dan miras aldığı UIKit ve AppKit ile çalışmanın tek yolu sınıflardır. Ayrıca, nesne kimliği (bir nesneye iki referans) ve kontrollü yaşam döngüsü gerektiren desenleri uygulamak için sınıflar gereklidir.
Referans türü semantiği — sınıfların temel özelliği. Bir sınıfı yeni bir değişkene atarken, Swift verileri değil referansı kopyalar. Aynı örneği referans alan tüm değişkenler, mevcut durumunu görür ve onu değiştirebilir. Bu davranış, her değişkenin bağımsız bir kopya aldığı değer türlerinden temel olarak farklıdır.
// Referans türü semantiği örneği
class User {
var name: String
init(name: String) { self.name = name }
}
let user1 = User(name: "Alice")
let user2 = user1 // user2 — aynı referans
user2.name = "Bob"
print(user1.name) // "Bob" — user2 üzerinden değiştirildi!
// === operatörüyle kimlik kontrolü
print(user1 === user2) // true — aynı nesne
=== (kimlik) ve !== operatörleri, iki değişkenin aynı sınıf örneğine referans verip vermediğini kontrol eder. Bu, özellik değerlerini karşılaştıran == (eşitlik) operatöründen farklıdır. === operatörü struct için kullanılamaz — değer türlerinin kimliği yoktur.
Kalıtım — bir sınıfın bir üst sınıfın özelliklerini ve yöntemlerini benimseyebildiği bir mekanizmadır. Swift'te bir sınıf yalnızca bir üst sınıftan miras alabilir (tek kalıtım), ancak birden çok protokolü uygulayabilir. override anahtar sözcüğü, miras alınan bir yöntemi veya özelliği geçersiz kılmaya izin verir.
Başka bir sınıftan miras almayan her sınıf, otomatik olarak temel sınıf haline gelir (NSObject ile karıştırmayın). Bir alt sınıf, adından sonra iki nokta üst üste koyarak üst sınıfı belirtir. Bir alt sınıf, üst sınıfın yöntemini geçersiz kılarsa, üst sınıfın davranışını korumak için super.yöntem()'i çağırmalıdır — bu bir derleyici gereksinimidir.
class'tan önceki final anahtar sözcüğü kalıtımı engeller. Derleyici, statik gönderme yoluyla final sınıfının yöntem çağrılarını optimize ederek performansı artırabilir. Genişletilmesi amaçlanmayan sınıflar için final kullanın — niyetinizi belgeler ve kodu hızlandırır.
// Swift'te sınıf kalıtımı örneği
class Vehicle {
var speed: Double = 0
func description() -> String {
"Speed: \(speed) km/h"
}
}
// Car, Vehicle'dan miras alır
class Car: Vehicle {
var brand: String = "Unknown"
override func description() -> String {
"\(brand) - \(speed) km/h"
}
}
// Final sınıf — kalıtımı engeller
final class ElectricCar: Car {
var batteryLevel: Double = 100
}
let tesla = ElectricCar()
tesla.brand = "Tesla"
tesla.speed = 120
print(tesla.description()) // "Tesla - 120.0 km/h"
Kalıtım güçlü ancak sorumluluk gerektiren bir mekanizmadır. Derin hiyerarşiler (5+ seviye) bakım ve testi zorlaştırır. Kalıtım olmadan işlevsel yeniden kullanım için, extension ve protokol odaklı programlama ile protokoller kullanın — Apple'ın derin sınıf hiyerarşilerine alternatif olarak önerdiği yaklaşım.
Swift, sınıf bellek yönetimi için ARC'yi (Otomatik Referans Sayımı) kullanır. Her sınıf örneğinin bir güçlü referans sayacı vardır. Yeni bir güçlü referans oluşturulduğunda sayaç artar; yok edildiğinde azalır. Sayaç sıfıra ulaştığında bellek serbest bırakılır.
Deinit — bir sınıf örneği serbest bırakılmadan önce otomatik olarak çağrılan yöntem. Kaynakları serbest bırakır: dosyaları kapatır, bildirim aboneliklerini iptal eder, zamanlayıcıları durdurur. Deinit yalnızca sınıflar için kullanılabilir — struct'lar ve enum'lar buna sahip değildir.
Güçlü referans döngülerini (retain cycles) önlemek için Swift, weak ve unowned referanslar sağlar. Weak, nesne serbest bırakıldığında otomatik olarak nil olan isteğe bağlı bir referanstır. Unowned isteğe bağlı değildir ancak geçerli bağlamdan daha uzun yaşaması garanti edilen bir nesneyi referans alır. Tipik bir retain cycle, ebeveyn-çocuk ilişkisinde oluşur: çocuk, ebeveyne güçlü bir referans tutar.
// ARC ve zayıf referans örneği
class Parent {
var name: String
var child: Child?
init(name: String) { self.name = name }
deinit { print("\(name) serbest bırakıldı") }
}
class Child {
var name: String
weak var parent: Parent? // weak retain cycle'ı önler
init(name: String) { self.name = name }
deinit { print("\(name) serbest bırakıldı") }
}
var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent
parent = nil // Her iki nesne de serbest bırakıldı!
// Weak olmadan bir retain cycle oluşturur
Alt nesneden üst nesneye olan referanslar ve closure'lardaki yakalama listeleri için her zaman weak kullanın. Unowned'ı yalnızca nesnenin geçerli bağlamdan daha uzun yaşayacağından emin olduğunuzda kullanın — unowned'ın yanlış kullanımı, serbest bırakılmış belleğe erişirken çökmeye neden olabilir.
class ve struct arasındaki seçim, performansı, iş parçacığı güvenliğini ve API tasarımını etkileyen mimari bir karardır. Her durumda doğru kararı vermek için temel farklar tablosunu inceleyin.
| Özellik | class | struct |
|---|---|---|
| Tür | Referans türü | Değer türü (kopya) |
| Bellek | Yığın + ARC | Yığıt / satır içi |
| Kalıtım | Destekler (tek ebeveyn) | Desteklemez |
| Deinit | Var | Yok |
| Kimlik (===) | Destekler | Desteklemez |
| Mutating | Gerekmez (her zaman mutating) | Sadece mutating ile |
| Memberwise init | Oluşturulmaz | Otomatik oluşturulur |
| İş parçacığı güvenliği | Garanti edilmez (paylaşılan durum) | Garanti edilir (kopyalama) |
Paylaşılan kimlik (kodun birden çok bölümünün tek bir nesneyle çalışması), kalıtım veya Objective-C çalışma zamanıyla etkileşim gerektiğinde sınıfları kullanın. Diğer her şey için struct'lar tercih edilir — daha hızlıdır, çok iş parçacıklı kodda daha güvenlidir ve bellek yönetimi gerektirmez.
Apple'ın varsayılan olarak struct kullanma önerisine rağmen, birkaç belirli senaryoda sınıflar gereklidir. Her birini pratik örneklerle inceleyelim.
iOS ve macOS'teki tüm UI bileşenleri, UIView'den (iOS) veya NSView'den (macOS) miras alan sınıflardır. UIViewController'ı bir struct ile değiştiremezsiniz — kaynakları serbest bırakmak için kalıtım ve deinit gerektirir. UIKit ile çalışırken, denetleyiciler, görünümler ve bunların temsilcileri için sınıfları kullanın.
Singleton deseni (tüm uygulama için tek bir sınıf örneği) referans semantiği gerektirir. Yöneticiler: NetworkManager, SettingsManager, AnalyticsService — genellikle paylaşılan bir static özelliğe sahip sınıflar olarak uygulanır. Struct'lar uygun değildir çünkü her kopya bağımsız bir örnek olacaktır.
Bir nesnenin tek doğruluk kaynağı olması gerektiğinde ve modüller arasında referans olarak iletildiğinde — class kullanın. Bu, bir nesneyi bir yerde değiştirmenin tüm bağımlı bileşenlerde görünür olması gereken durum yönetimi için geçerlidir. SwiftUI'de ObservableObject için sınıflar zorunludur.
// ObservableObject — SwiftUI için class gerekli
import SwiftUI
class AppViewModel: ObservableObject {
@Published var isLoggedIn: Bool = false
@Published var username: String = ""
func login(user: String) {
isLoggedIn = true
username = user
}
}
// SwiftUI View'da kullanım
struct ContentView: View {
@StateObject var viewModel = AppViewModel()
var body: some View {
Text(viewModel.isLoggedIn ? "Hoş geldiniz" : "Giriş yap")
}
}
Kural: bir nesnenin kimliği (iki referans -> bir nesne) olması gerekiyorsa, tek bir örnek olması gerekiyorsa veya UIKit/Objective-C ile çalışması gerekiyorsa — class'ı seçin. Bir nesne yalnızca veri içeriyorsa — struct'ı seçin.
Sıkça Sorulan Sorular
Class, Swift'te kalıtımı, sonlandırmayı ve bellek yönetimi için ARC'yi destekleyen bir referans türüdür. Sınıf örnekleri yığında saklanır ve değişkenler, nesnenin kopyasını değil, referansını içerir.
Class — referans türü (referans olarak iletilir), kalıtım ve deinit'i destekler. Struct — değer türü (kopyalanır), kalıtımı desteklemez, ancak protokolleri uygular ve otomatik olarak memberwise init alır. Swift, varsayılan tür olarak struct'ı önerir.
ARC (Otomatik Referans Sayımı) — Swift sınıfları için bir bellek yönetimi mekanizmasıdır. Her örneğin bir güçlü referans sayacı vardır. Sayaç sıfıra ulaştığında bellek serbest bırakılır. Weak ve unowned referanslar, nesneler arasındaki retain cycle'ları önler.
Deinit — belleği serbest bırakılmadan önce otomatik olarak çağrılan bir sınıf yöntemidir. Dosyaları kapatmak, bildirim aboneliklerini iptal etmek ve diğer temizlik işlemleri için kullanılır. Deinit yalnızca sınıflarda bulunur — struct'larda yoktur.
UIKit/AppKit UI bileşenleri, singleton, SwiftUI'de ObservableObject, paylaşılan kimliğe sahip nesneler (delegate, observer) ve Objective-C çalışma zamanıyla çalışırken class kullanın. Veri modelleri, DTO'lar ve yapılandırmalar için struct tercih edilir.
Ö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