Struct — یک نوع-مقدار (value type) در زبان Swift است که نمونههای آن هنگام انتقال بین بخشهای کد کپی میشوند. بر خلاف کلاسها، structها از وراثت پشتیبانی نمیکنند، اما پروتکلها را پیادهسازی میکنند، شامل ویژگیها و متدها هستند و مدیریت حافظه قابل پیشبینی بدون ARC را فراهم میکنند. بر اساس راهنمای زبان برنامهنویسی Swift، ۲۰۲۶، struct بلوک ساختمانی پایه Swift است — حتی انواع استاندارد Int، String، Array و Dictionary به عنوان struct پیادهسازی شدهاند. این زبان structها را به عنوان انتخاب اولویتدار برای مدلسازی دادهها توصیه میکند.
نکات اصلی
Struct (ساختار) — یک نوع داده ترکیبی در Swift است که ویژگیها و متدهای مرتبط را در یک موجودیت واحد گروهبندی میکند. بر خلاف کلاسها، structها value types هستند: هنگام ارسال به تابع یا انتساب به متغیر جدید، یک کپی مستقل از struct ایجاد میشود، نه یک ارجاع به شیء اصلی.
Swift از structها برای تمام انواع اولیه استفاده میکند: Int، Double، String، Bool، Array، Dictionary و Set. این بدان معناست که حتی عدد پایه Int نیز مانند یک struct رفتار میکند — هنگام انتساب یک کپی ایجاد میشود. توسعهدهنده میتواند struct خود را با مجموعه دلخواهی از ویژگیها و متدها تعریف کند.
طبق Swift Evolution (SE-0143)، تصمیم به پیادهسازی انواع استاندارد به عنوان structها به دلیل عملکرد و قابلیت پیشبینی بوده است. Value types چرخههای ارجاعی ایجاد نمیکنند، به شمارش مرجع ARC نیاز ندارند و تضمین میکنند که تغییر در کپی بر اصل تأثیر نمیگذارد — این برای تغییرناپذیری دادهها در سناریوهای چندنخی حیاتی است.
Value type semantics — تفاوت کلیدی بین struct و class است. هنگامی که یک struct را به متغیر جدید انتساب میدهید یا به تابعی ارسال میکنید، Swift یک کپی مستقل از تمام دادهها ایجاد میکند. هرگونه تغییر در کپی بر اصل تأثیر نمیگذارد که عوارض جانبی مشخصه انواع ارجاعی را حذف میکند.
// مثال معناشناسی value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2 یک کپی مستقل از p1 است
p2.x = 99 // فقط p2 تغییر میکند
print(p1.x) // ۱۰ — p1 بدون تغییر
print(p2.x) // ۹۹
Swift از Copy-on-Write (COW) برای بهینهسازی کپی استفاده میکند. اگر چندین متغیر به یک struct ارجاع دهند اما هیچکدام دادهها را تغییر ندهند، کپی واقعی رخ نمیدهد. Swift حافظه را بین متغیرها تا اولین تغییر به اشتراک میگذارد — سپس یک کپی واقعی ایجاد میشود. این کار از عملیات تخصیص اضافی جلوگیری میکند و کار با مجموعهها را سرعت میبخشد.
به طور پیشفرض، متدهای struct نمیتوانند ویژگیهای آن را تغییر دهند — Swift نیاز به ذکر صریح mutating برای متدهایی که تغییر ایجاد میکنند دارد. این محدودیت از تغییر تصادفی جلوگیری میکند و کد را قابل پیشبینی میسازد: اگر متدی با mutating علامتگذاری نشده باشد، تضمین میشود که struct را تغییر نمیدهید.
هنگامی که کلمه کلیدی mutating را قبل از متد اضافه میکنید، Swift توانایی نوشتن مقادیر جدید در ویژگیهای struct را به دست میآورد. در واقع، متد حتی میتواند نمونه struct را کاملاً با نمونه جدیدی از طریق self = جایگزین کند. این مکانیسم برای مثال در انواع Option و Result استفاده میشود.
// struct با متد mutating
struct Counter {
private var value: Int = 0
// متد mutating — میتواند ویژگیها را تغییر دهد
mutating func increment() {
value += 1
}
// متد mutating میتواند self را کاملاً جایگزین کند
mutating func reset() {
self = Counter()
}
// متد non-mutating — فقط خواندنی
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // ۱
counter.reset()
print(counter.currentValue()) // ۰
قوانین mutating: struct باید با var اعلام شود، نه let — در struct ثابت نمیتوان متد mutating را فراخوانی کرد. کامپایلر این را در مرحله ساخت بررسی میکند: تلاش برای فراخوانی متد mutating بر روی ثابت let منجر به خطای کامپایل میشود.
انتخاب بین struct و class — یکی از تصمیمات اساسی در Swift است. هر دو نوع میتوانند شامل ویژگیها، متدها، مقداردهندههای اولیه باشند و پروتکلها را پیادهسازی کنند، اما تفاوتهای اساسی در معناشناسی حافظه، وراثت و مدیریت چرخه حیات دارند.
| ویژگی | struct | class |
|---|---|---|
| نوع | Value type (کپی میشود) | Reference type (ارجاع) |
| وراثت | پشتیبانی نمیکند | پشتیبانی میکند |
| ARC / شمارش مرجع | نیاز ندارد | نیاز به ARC دارد |
| مقداردهی زدایی | پشتیبانی نمیکند | از deinit پشتیبانی میکند |
| تغییر ویژگیها در ثابت | فقط از طریق var | از طریق let ممکن است (ارجاع ثابت است) |
| تبدیل نوع | پشتیبانی نمیکند | پشتیبانی میکند |
| ذخیره در مجموعهها | مستقیماً ذخیره میشود (مقدار) | به عنوان ارجاع ذخیره میشود (اشارهگر) |
structها زمانی ترجیح داده میشوند که دادهها نیاز به وراثت ندارند، نباید هویت مشترک داشته باشند (مثلاً مختصات، ابعاد، پیکربندی) و بین ماژولها منتقل میشوند. کلاسها برای کامپوننتهای UI (UIView، UIViewController)، singleton و اشیاء با هویت مشترک انتخاب میشوند.
Apple استفاده از struct را به عنوان نوع پیشفرض برای مدلسازی دادهها در Swift توصیه میکند. structها به دلیل معناشناسی قابل پیشبینی کپی و عدم سربار شمارش مرجع برای اکثر سناریوها مناسب هستند. موارد معمولی را که struct انتخاب بهینه است بررسی میکنیم.
اگر موجودیت حاوی دادههایی بدون نیاز به وراثت است (Product، User، Order، Point)، از struct استفاده کنید. کامپایلر به طور خودکار memberwise initializer را تولید میکند — نیازی به نوشتن دستی init نیست. Equatable و Hashable نیز به طور خودکار برای structهایی که همه ویژگیهایشان این پروتکلها را برآورده میکنند پیادهسازی میشوند.
برای پیکربندیها، تنظیمات و پرچمهایی که پس از ایجاد تغییر نمیکنند، struct نسبت به class ارجحیت دارد. struct ثابت (let) تغییرناپذیری تمام فیلدهای تو در تو را تضمین میکند — در class این فقط به ارجاع مربوط میشود، نه به محتوای شیء.
structها به دلیل value semantics در محیط چندنخی ایمن هستند. هر نخ یک کپی مستقل از داده دریافت میکند و بر نخهای دیگر تأثیر نمیگذارد. شرایط مسابقه بین نخها برای value types غیرممکن است، که struct را به انتخاب ترجیحی برای مدلها در SwiftUI تبدیل میکند (ObservableObject نیاز به class دارد، اما @State از struct استفاده میکند).
// مثال استفاده از struct برای مدل داده
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// ویژگی computed — غیر mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// مقداردهنده اولیه خودکار memberwise
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// کپی برای چندنخی ایمن است
var userCopy = user
userCopy.isPremium = false
// user.isPremium درست باقی میماند
زمانی از class استفاده کنید که نیاز به وراثت (کامپوننتهای UIKit/AppKit)، هویت مشترک (delegate، observer) یا چرخه حیات کنترلشده اشیاء (deinit) دارید. برای بقیه موارد — struct.
سؤالات متداول
Struct در Swift — یک نوع-مقدار (value type) است که هنگام انتقال بین بخشهای کد کپی میشود. structها میتوانند شامل ویژگیها، متدها، مقداردهندههای اولیه باشند و پروتکلها را پیادهسازی کنند. انواع پایه Swift (Int، String، Array) به عنوان struct پیادهسازی شدهاند.
Struct — value type (هنگام انتساب کپی میشود)، از وراثت پشتیبانی نمیکند و نیازی به ARC ندارد. Class — reference type (با ارجاع منتقل میشود)، از وراثت، مقداردهی زدایی و شمارش مرجع پشتیبانی میکند. توسعهدهندگان struct را به عنوان نوع پیشفرض توصیه میکنند.
Mutating — کلمه کلیدی است که نشان میدهد متد struct میتواند ویژگیهای آن را تغییر دهد. بدون mutating کامپایلر تغییر فیلدها را ممنوع میکند. متدهای mutating فقط روی متغیرهای اعلامشده با var قابل فراخوانی هستند، نه let.
Copy-on-Write (COW) — بهینهسازی Swift برای structها است که در آن کپی واقعی دادهها تا لحظه اولین تغییر به تعویق میافتد. تا زمانی که همه متغیرها فقط struct را میخوانند، یک ناحیه حافظه را به اشتراک میگذارند. این کار عملکرد را هنگام کار با مجموعههای بزرگ افزایش میدهد.
از struct برای مدلهای داده بدون وراثت، پیکربندیها، DTO و سناریوهای چندنخی استفاده کنید. از class برای کامپوننتهای UI UIKit/AppKit، singleton، موجودیتهای با هویت مشترک (delegate، observer) و اشیاء نیازمند مقداردهی زدایی استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید