struct — چیست، مفاهیم کلیدی و نحوه کار در Swift

نویسنده: IT Sectr منتشر شده: 2026-06-17 زمان مطالعه: 7 دقیقه

Struct — یک نوع-مقدار (value type) در زبان Swift است که نمونه‌های آن هنگام انتقال بین بخش‌های کد کپی می‌شوند. بر خلاف کلاس‌ها، structها از وراثت پشتیبانی نمی‌کنند، اما پروتکل‌ها را پیاده‌سازی می‌کنند، شامل ویژگی‌ها و متدها هستند و مدیریت حافظه قابل پیش‌بینی بدون ARC را فراهم می‌کنند. بر اساس راهنمای زبان برنامه‌نویسی Swift، ۲۰۲۶، struct بلوک ساختمانی پایه Swift است — حتی انواع استاندارد Int، String، Array و Dictionary به عنوان struct پیاده‌سازی شده‌اند. این زبان structها را به عنوان انتخاب اولویت‌دار برای مدل‌سازی داده‌ها توصیه می‌کند.

نکات اصلی

  • Struct — نوع-مقدار در Swift است که هنگام انتساب کپی می‌شود و با مقدار منتقل می‌شود، نه با ارجاع.
  • Copy-on-Write — بهینه‌سازی‌ای که در آن کپی واقعی داده‌ها تنها هنگام تغییر مقدار رخ می‌دهد، نه هنگام انتساب.
  • Mutating — کلمه کلیدی که برای متدهای تغییردهنده ویژگی‌های struct مورد نیاز است.
  • پروتکل‌ها — structها می‌توانند پروتکل‌ها و توسعه‌دهنده‌ها را پیاده‌سازی کنند که انعطاف‌پذیری بدون وراثت را فراهم می‌کند.
  • ایمنی — عدم وجود چرخه‌های ارجاعی structها را برای کدهای چندنخی و مدل‌های داده ترجیح‌پذیر می‌کند.

struct در Swift چیست؟

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 نیاز ندارند و تضمین می‌کنند که تغییر در کپی بر اصل تأثیر نمی‌گذارد — این برای تغییرناپذیری داده‌ها در سناریوهای چندنخی حیاتی است.

struct به عنوان value type

Value type semantics — تفاوت کلیدی بین struct و class است. هنگامی که یک struct را به متغیر جدید انتساب می‌دهید یا به تابعی ارسال می‌کنید، Swift یک کپی مستقل از تمام داده‌ها ایجاد می‌کند. هرگونه تغییر در کپی بر اصل تأثیر نمی‌گذارد که عوارض جانبی مشخصه انواع ارجاعی را حذف می‌کند.

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)         // ۹۹

بهینه‌سازی Copy-on-Write

Swift از Copy-on-Write (COW) برای بهینه‌سازی کپی استفاده می‌کند. اگر چندین متغیر به یک struct ارجاع دهند اما هیچکدام داده‌ها را تغییر ندهند، کپی واقعی رخ نمی‌دهد. Swift حافظه را بین متغیرها تا اولین تغییر به اشتراک می‌گذارد — سپس یک کپی واقعی ایجاد می‌شود. این کار از عملیات تخصیص اضافی جلوگیری می‌کند و کار با مجموعه‌ها را سرعت می‌بخشد.

تغییرپذیری و متدهای mutating

به طور پیش‌فرض، متدهای struct نمی‌توانند ویژگی‌های آن را تغییر دهند — Swift نیاز به ذکر صریح mutating برای متدهایی که تغییر ایجاد می‌کنند دارد. این محدودیت از تغییر تصادفی جلوگیری می‌کند و کد را قابل پیش‌بینی می‌سازد: اگر متدی با mutating علامت‌گذاری نشده باشد، تضمین می‌شود که struct را تغییر نمی‌دهید.

Mutating در عمل

هنگامی که کلمه کلیدی mutating را قبل از متد اضافه می‌کنید، Swift توانایی نوشتن مقادیر جدید در ویژگی‌های struct را به دست می‌آورد. در واقع، متد حتی می‌تواند نمونه struct را کاملاً با نمونه جدیدی از طریق self = جایگزین کند. این مکانیسم برای مثال در انواع Option و Result استفاده می‌شود.

swift
// 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: مقایسه

انتخاب بین struct و class — یکی از تصمیمات اساسی در Swift است. هر دو نوع می‌توانند شامل ویژگی‌ها، متدها، مقداردهنده‌های اولیه باشند و پروتکل‌ها را پیاده‌سازی کنند، اما تفاوت‌های اساسی در معناشناسی حافظه، وراثت و مدیریت چرخه حیات دارند.

ویژگیstructclass
نوعValue type (کپی می‌شود)Reference type (ارجاع)
وراثتپشتیبانی نمی‌کندپشتیبانی می‌کند
ARC / شمارش مرجعنیاز نداردنیاز به ARC دارد
مقداردهی زداییپشتیبانی نمی‌کنداز deinit پشتیبانی می‌کند
تغییر ویژگی‌ها در ثابتفقط از طریق varاز طریق let ممکن است (ارجاع ثابت است)
تبدیل نوعپشتیبانی نمی‌کندپشتیبانی می‌کند
ذخیره در مجموعه‌هامستقیماً ذخیره می‌شود (مقدار)به عنوان ارجاع ذخیره می‌شود (اشاره‌گر)

structها زمانی ترجیح داده می‌شوند که داده‌ها نیاز به وراثت ندارند، نباید هویت مشترک داشته باشند (مثلاً مختصات، ابعاد، پیکربندی) و بین ماژول‌ها منتقل می‌شوند. کلاس‌ها برای کامپوننت‌های UI (UIView، UIViewController)، singleton و اشیاء با هویت مشترک انتخاب می‌شوند.

زمان انتخاب struct

Apple استفاده از struct را به عنوان نوع پیش‌فرض برای مدل‌سازی داده‌ها در Swift توصیه می‌کند. structها به دلیل معناشناسی قابل پیش‌بینی کپی و عدم سربار شمارش مرجع برای اکثر سناریوها مناسب هستند. موارد معمولی را که struct انتخاب بهینه است بررسی می‌کنیم.

مدل‌های داده بدون وراثت

اگر موجودیت حاوی داده‌هایی بدون نیاز به وراثت است (Product، User، Order، Point)، از struct استفاده کنید. کامپایلر به طور خودکار memberwise initializer را تولید می‌کند — نیازی به نوشتن دستی init نیست. Equatable و Hashable نیز به طور خودکار برای structهایی که همه ویژگی‌هایشان این پروتکل‌ها را برآورده می‌کنند پیاده‌سازی می‌شوند.

داده‌های تغییرناپذیر (immutable)

برای پیکربندی‌ها، تنظیمات و پرچم‌هایی که پس از ایجاد تغییر نمی‌کنند، struct نسبت به class ارجحیت دارد. struct ثابت (let) تغییرناپذیری تمام فیلدهای تو در تو را تضمین می‌کند — در class این فقط به ارجاع مربوط می‌شود، نه به محتوای شیء.

کد چندنخی

structها به دلیل value semantics در محیط چندنخی ایمن هستند. هر نخ یک کپی مستقل از داده دریافت می‌کند و بر نخ‌های دیگر تأثیر نمی‌گذارد. شرایط مسابقه بین نخ‌ها برای value types غیرممکن است، که struct را به انتخاب ترجیحی برای مدل‌ها در SwiftUI تبدیل می‌کند (ObservableObject نیاز به class دارد، اما @State از struct استفاده می‌کند).

swift
// مثال استفاده از 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 چیست؟

Struct در Swift — یک نوع-مقدار (value type) است که هنگام انتقال بین بخش‌های کد کپی می‌شود. structها می‌توانند شامل ویژگی‌ها، متدها، مقداردهنده‌های اولیه باشند و پروتکل‌ها را پیاده‌سازی کنند. انواع پایه Swift (Int، String، Array) به عنوان struct پیاده‌سازی شده‌اند.

تفاوت بین struct و class در Swift چیست؟

Struct — value type (هنگام انتساب کپی می‌شود)، از وراثت پشتیبانی نمی‌کند و نیازی به ARC ندارد. Class — reference type (با ارجاع منتقل می‌شود)، از وراثت، مقداردهی زدایی و شمارش مرجع پشتیبانی می‌کند. توسعه‌دهندگان struct را به عنوان نوع پیش‌فرض توصیه می‌کنند.

mutating در struct Swift چیست؟

Mutating — کلمه کلیدی است که نشان می‌دهد متد struct می‌تواند ویژگی‌های آن را تغییر دهد. بدون mutating کامپایلر تغییر فیلدها را ممنوع می‌کند. متدهای mutating فقط روی متغیرهای اعلام‌شده با var قابل فراخوانی هستند، نه let.

Copy-on-Write در Swift چیست؟

Copy-on-Write (COW) — بهینه‌سازی Swift برای structها است که در آن کپی واقعی داده‌ها تا لحظه اولین تغییر به تعویق می‌افتد. تا زمانی که همه متغیرها فقط struct را می‌خوانند، یک ناحیه حافظه را به اشتراک می‌گذارند. این کار عملکرد را هنگام کار با مجموعه‌های بزرگ افزایش می‌دهد.

چه زمانی از struct و چه زمانی از class در Swift استفاده کنیم؟

از struct برای مدل‌های داده بدون وراثت، پیکربندی‌ها، DTO و سناریوهای چندنخی استفاده کنید. از class برای کامپوننت‌های UI UIKit/AppKit، singleton، موجودیت‌های با هویت مشترک (delegate، observer) و اشیاء نیازمند مقداردهی زدایی استفاده کنید.

خلاصه

  • Struct — یک نوع-مقدار (value type) در Swift است که هنگام انتساب کپی می‌شود و رفتار قابل پیش‌بینی بدون عوارض جانبی بین کپی‌ها را تضمین می‌کند.
  • Copy-on-Write عملکرد structها را بهینه می‌کند — کپی واقعی فقط در اولین تغییر رخ می‌دهد، نه در هر انتساب.
  • انواع استاندارد Swift — Int، String، Array، Dictionary — به عنوان struct پیاده‌سازی شده‌اند که value semantics را برای تمام عملیات پایه تضمین می‌کند.
  • Mutating — کلمه کلیدی اجباری برای متدهایی که ویژگی‌های struct را تغییر می‌دهند؛ فراخوانی فقط روی نمونه‌های var امکان‌پذیر است.
  • structها از وراثت پشتیبانی نمی‌کنند اما پروتکل‌ها را پیاده‌سازی می‌کنند و می‌توانند از توسعه‌دهنده‌ها برای افزودن قابلیت استفاده کنند.
  • Equatable و Hashable به طور خودکار برای structهایی که همه ویژگی‌هایشان این پروتکل‌ها را برآورده می‌کنند پیاده‌سازی می‌شوند — این کار مقایسه و استفاده در مجموعه‌ها را ساده می‌کند.
  • Apple struct را به عنوان نوع پیش‌فرض توصیه می‌کند — فقط زمانی از class استفاده کنید که وراثت، هویت مشترک یا چرخه حیات کنترل‌شده شیء مورد نیاز است.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید