Class — یک نوع مرجع (reference type) در زبان Swift است که نمونههای آن با ارجاع منتقل میشوند، نه با کپی کردن در هنگام تخصیص. برخلاف ساختارها، کلاسها از وراثت، مقدارزدایی و شمارش خودکار مراجع ARC برای مدیریت حافظه پشتیبانی میکنند. به گفته Swift Programming Language Guide, 2026، class برای کار با چارچوبهای UI اپل (UIKit, AppKit) و پیادهسازی الگوهایی که نیاز به هویت مشترک شیء دارند ضروری است. انتخاب بین class و struct یکی از تصمیمهای کلیدی معماری در Swift است.
نکات اصلی
Class (کلاس) — یک نوع مرجع ترکیبی در Swift است که ویژگیها و متدها را در یک موجودیت واحد با پشتیبانی از وراثت و ارسال پویا گروهبندی میکند. برخلاف struct، نمونه کلاس در heap ایجاد میشود و متغیر یک ارجاع به این نمونه را ذخیره میکند، نه خود دادهها.
وقتی یک متغیر کلاس را به متغیر دیگری تخصیص میدهید، هر دو به یک شیء در حافظه ارجاع میدهند. تغییرات از طریق یک ارجاع از طریق دیگری قابل مشاهده است — این ویژگی بنیادی reference types است که در الگوهای تفویض اختیار، مشاهده و حالت اشتراکی استفاده میشود.
به گفته Apple Swift Documentation، کلاسها تنها راه کار با UIKit و AppKit هستند، جایی که همه کامپوننتهای UI از UIView و UIViewController ارث میبرند. علاوه بر این، کلاسها برای پیادهسازی الگوهایی که نیاز به هویت شیء (دو ارجاع به یک شیء) و طول عمر کنترلشده دارند ضروری هستند.
معناشناسی reference type — ویژگی کلیدی کلاسهاست. هنگام تخصیص کلاس به یک متغیر جدید، Swift ارجاع را کپی میکند، نه دادهها را. همه متغیرهایی که به یک نمونه ارجاع میدهند وضعیت فعلی آن را میبینند و میتوانند آن را تغییر دهند. این رفتار اساساً با value types متفاوت است، جایی که هر متغیر یک کپی مستقل دریافت میکند.
// مثال معناشناسی reference type
class User {
var name: String
init(name: String) { self.name = name }
}
let user1 = User(name: "Alice")
let user2 = user1 // user2 — ارجاع یکسان
user2.name = "Bob"
print(user1.name) // "Bob" — از طریق user2 تغییر کرد!
// بررسی هویت با عملگر ===
print(user1 === user2) // true — شیء یکسان
عملگرهای === (هویت) و !== بررسی میکنند که آیا دو متغیر به یک نمونه کلاس ارجاع میدهند. این تفاوت با == (برابری) است که مقادیر ویژگیها را مقایسه میکند. برای struct عملگر === در دسترس نیست — value types هویت ندارند.
وراثت — مکانیزمی که به یک کلاس امکان میدهد ویژگیها و متدهای کلاس والد را به ارث ببرد. در Swift یک کلاس میتواند فقط از یک والد ارث ببرد (single inheritance)، اما میتواند چندین پروتکل را پیادهسازی کند. کلمه کلیدی override به شما امکان بازنویسی یک متد یا ویژگی به ارث برده را میدهد.
هر کلاسی که از کلاس دیگری ارث نمیبرد به طور خودکار یک کلاس پایه میشود (با NSObject اشتباه نشود). زیرکلاس والد را با دو نقطه بعد از نام مشخص میکند. اگر زیرکلاس متد والد را بازنویسی کند، باید super.متد() را برای حفظ رفتار والد فراخوانی کند — این یک الزام کامپایلر است.
کلمه کلیدی final قبل از class وراثت را ممنوع میکند. کامپایلر میتواند فراخوانیهای متدهای کلاس نهایی را از طریق static dispatch بهینهسازی کند که عملکرد را افزایش میدهد. از final برای کلاسهایی که برای گسترش در نظر گرفته نشدهاند استفاده کنید — این قصد شما را مستند میکند و کد را سریعتر میکند.
// مثال وراثت کلاس در Swift
class Vehicle {
var speed: Double = 0
func description() -> String {
"Speed: \(speed) km/h"
}
}
// Car از Vehicle ارث میبرد
class Car: Vehicle {
var brand: String = "Unknown"
override func description() -> String {
"\(brand) - \(speed) km/h"
}
}
// Final class — از وراثت جلوگیری میکند
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"
وراثت کلاسها مکانیزمی قدرتمند اما مسئولیتپذیر است. سلسلهمراتب عمیق (5+ سطح) نگهداری و آزمایش را دشوار میکند. برای استفاده مجدد از قابلیتها بدون وراثت از پروتکلها با extension و برنامهنویسی پروتکلمحور استفاده کنید — رویکردی که اپل به عنوان جایگزینی برای سلسلهمراتب عمیق کلاس ترویج میکند.
Swift از ARC (Automatic Reference Counting) برای مدیریت حافظه کلاسها استفاده میکند. هر نمونه کلاس یک شمارنده ارجاع قوی دارد. هنگام ایجاد یک ارجاع قوی جدید شمارنده افزایش مییابد؛ هنگام نابودی کاهش مییابد. وقتی شمارنده به صفر میرسد، حافظه آزاد میشود.
Deinit — متدی که به طور خودکار قبل از آزادسازی نمونه کلاس فراخوانی میشود. در آن منابع آزاد میشوند: فایلها بسته میشوند، از اعلانها لغو اشتراک میشود، تایمرها متوقف میشوند. Deinit فقط در کلاسها وجود دارد — ساختارها و شمارشها آن را ندارند.
برای جلوگیری از چرخههای ارجاع قوی (retain cycles)، Swift ارجاعات weak و unowned را فراهم میکند. Weak — یک ارجاع اختیاری که با آزادسازی شیء به طور خودکار nil میشود. Unowned — غیراختیاری، اما به شیئی ارجاع میدهد که تضمین شده بیشتر از زمینه فعلی زنده میماند. retain cycle معمولی در رابطه parent-child رخ میدهد: child یک ارجاع قوی به parent نگه میدارد.
// مثال ARC و ارجاع ضعیف
class Parent {
var name: String
var child: Child?
init(name: String) { self.name = name }
deinit { print("\(name) آزاد شد") }
}
class Child {
var name: String
weak var parent: Parent? // weak از retain cycle جلوگیری میکند
init(name: String) { self.name = name }
deinit { print("\(name) آزاد شد") }
}
var parent: Parent? = Parent(name: "Anna")
parent?.child = Child(name: "Mia")
parent?.child?.parent = parent
parent = nil // هر دو شیء آزاد شدند!
// بدون weak یک retain cycle ایجاد میشد
همیشه از weak برای ارجاعات از شیء فرزند به والد و برای لیستهای capture در بستهها استفاده کنید. Unowned را فقط زمانی استفاده کنید که مطمئن هستید شیء از زمینه فعلی بیشتر زنده میماند — استفاده نادرست از unowned میتواند به crash هنگام دسترسی به حافظه آزادشده منجر شود.
انتخاب بین class و struct یک تصمیم معماری است که بر عملکرد، ایمنی نخ و طراحی API تأثیر میگذارد. جدول تفاوتهای کلیدی را بررسی کنید که به اتخاذ تصمیم صحیح در هر مورد خاص کمک میکند.
| ویژگی | class | struct |
|---|---|---|
| نوع | Reference type (ارجاع) | Value type (کپی) |
| حافظه | Heap + ARC | Stack / inline |
| وراثت | پشتیبانی میکند (یک والد) | پشتیبانی نمیکند |
| Deinit | دارد | ندارد |
| هویت (===) | پشتیبانی میکند | پشتیبانی نمیکند |
| Mutating | نیاز نیست (همیشه mutating) | فقط با mutating |
| Memberwise init | تولید نمیشود | به طور خودکار تولید میشود |
| ایمنی نخ | تضمین نشده (حالت اشتراکی) | تضمین شده (کپیبرداری) |
زمانی از کلاسها استفاده کنید که به هویت مشترک (چند بخش کد با یک شیء کار میکنند)، وراثت یا تعامل با Objective-C runtime نیاز دارید. برای بقیه موارد ساختارها ترجیح داده میشوند — آنها سریعتر، در کد چندنخی ایمنتر هستند و نیاز به مدیریت حافظه ندارند.
با وجود توصیه اپل به استفاده پیشفرض از struct، کلاسها در چند سناریوی خاص ضروری هستند. هر کدام را با مثالهای عملی بررسی میکنیم.
همه کامپوننتهای UI در iOS و macOS کلاسهایی هستند که از UIView (iOS) یا NSView (macOS) ارث میبرند. شما نمیتوانید UIViewController را با struct جایگزین کنید — به وراثت و deinit برای آزادسازی منابع نیاز دارد. هنگام کار با UIKit از کلاسها برای کنترلرها، viewها و delegateهای آنها استفاده کنید.
الگوی Singleton (یک نمونه کلاس برای کل برنامه) به معناشناسی ارجاعی نیاز دارد. مدیران: NetworkManager, SettingsManager, AnalyticsService — معمولاً به عنوان کلاسهایی با shared static property پیادهسازی میشوند. ساختارها مناسب نیستند زیرا هر کپی یک نمونه مستقل خواهد بود.
وقتی یک شیء باید تنها منبع حقیقت (single source of truth) باشد و بین ماژولها با ارجاع منتقل میشود — از class استفاده کنید. این مربوط به مدیریت حالتی است که تغییر شیء در یک مکان باید در همه کامپوننتهای وابسته قابل مشاهده باشد. برای ObservableObject در SwiftUI کلاسها اجباری هستند.
// ObservableObject — class لازم برای SwiftUI
import SwiftUI
class AppViewModel: ObservableObject {
@Published var isLoggedIn: Bool = false
@Published var username: String = ""
func login(user: String) {
isLoggedIn = true
username = user
}
}
// استفاده در نمای SwiftUI
struct ContentView: View {
@StateObject var viewModel = AppViewModel()
var body: some View {
Text(viewModel.isLoggedIn ? "خوش آمدید" : "ورود")
}
}
قاعده: اگر شیء باید هویت داشته باشد (دو ارجاع -> یک شیء)، یک نمونه منحصر به فرد باشد یا با UIKit/Objective-C کار کند — class را انتخاب کنید. اگر شیء فقط داده ذخیره میکند — struct را انتخاب کنید.
سوالات متداول
Class — یک نوع ارجاعی (reference type) در Swift است که از وراثت، مقدارزدایی و ARC برای مدیریت حافظه پشتیبانی میکند. نمونههای کلاسها در heap ذخیره میشوند و متغیرها حاوی ارجاع به شیء هستند، نه کپی آن.
Class — reference type (با ارجاع منتقل میشود)، از وراثت و deinit پشتیبانی میکند. Struct — value type (کپی میشود)، از وراثت پشتیبانی نمیکند اما پروتکلها را پیادهسازی میکند و memberwise init را به طور خودکار دریافت میکند. Swift struct را به عنوان نوع پیشفرض توصیه میکند.
ARC (Automatic Reference Counting) — مکانیزم مدیریت حافظه برای کلاسهای Swift. هر نمونه یک شمارنده ارجاع قوی دارد. وقتی شمارنده به صفر میرسد حافظه آزاد میشود. ارجاعات weak و unowned از چرخههای ارجاع قوی بین اشیاء جلوگیری میکنند.
Deinit — متد کلاس که به طور خودکار قبل از آزادسازی حافظه آن فراخوانی میشود. برای بستن فایلها، لغو اشتراک اعلانها و سایر عملیات پایانی استفاده میشود. Deinit فقط در کلاسها وجود دارد — ساختارها آن را ندارند.
از class برای کامپوننتهای UI UIKit/AppKit، singleton، ObservableObject در SwiftUI، اشیاء با هویت مشترک (delegate, observer) و هنگام کار با Objective-C runtime استفاده کنید. برای مدلهای داده، DTO و تنظیمات struct ترجیح داده میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید