Protocol در Swift — قراردادی است که مجموعهای از الزامات را تعریف میکند که هر نوع پذیرنده باید آنها را برآورده کند. پروتکلها اساس برنامهنویسی پروتکلمحور (POP) را تشکیل میدهند — پارادایمی که توسط Apple برای Swift در کنار OOP کلاسیک توصیه شده است. به گفته Apple Documentation, 2026، ساختارها، کلاسها و enum میتوانند پروتکلها را بپذیرند که معماری را انعطافپذیر و قابل آزمایش میکند.
نکات کلیدی
Protocol — یک رابط انتزاعی است که تعیین میکند یک نوع چه کارهایی باید انجام دهد، اما نه اینکه چگونه انجام دهد. در Swift، پروتکل مشابه رابطهای Java یا Go است، اما با قابلیتهای اضافی.
پروتکل میتواند نیاز داشته باشد:
{ get } یا { get set }طبق WWDC 2015، Apple برنامهنویسی پروتکلمحور را به عنوان رویکردی بنیادی برای معماری برنامههای Swift معرفی کرد. برخلاف OOP که در آن وراثت کلاس سلسلهمراتب سفت و سختی ایجاد میکند، POP ترکیب پروتکلها را پیشنهاد میدهد. این انعطافپذیری میدهد: یک نوع میتواند با چندین پروتکل مطابقت داشته باشد و الزامات و پیادهسازیهای آنها را از طریق extensions دریافت کند.
Protocol با کلمه کلیدی protocol به همراه نام و بدنه اعلام میشود.
protocol Drawable {
func draw(context: CGContext)
var boundingBox: CGRect { get }
}
نوع پروتکل را با دو نقطه بعد از نام میپذیرد:
struct Circle: Drawable {
let center: CGPoint
let radius: CGFloat
func draw(context: CGContext) {
context.addArc(center: center, radius: radius, ...)
}
var boundingBox: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
}
یک نوع میتواند چندین پروتکل را با کاما بپذیرد: struct MyType: ProtocolA, ProtocolB. کامپایلر بررسی میکند که همه الزامات هر پروتکل برآورده شده باشند.
Property requirements با کلمه کلیدی var و مشخصکنندههای دسترسی { get } یا { get set } مشخص میشوند.
protocol UserProtocol {
var name: String { get }
var age: Int { get set }
static var maxAge: Int { get }
mutating func updateName(_ newName: String)
}
کلمه کلیدی mutating در پروتکل به این معنی است که متد میتواند self را تغییر دهد. ساختارها باید چنین متدی را به صورت mutating پیادهسازی کنند، کلاسها میتوانند آن را حذف کنند. Method requirements با امضای کامل شامل برچسبهای پارامتر مشخص میشوند.
Protocol میتواند پروتکل دیگری را به ارث برده و الزامات جدیدی اضافه کند. این یک سلسلهمراتب قراردادی بدون وابستگی سفت و سخت به کلاسها ایجاد میکند.
protocol Vehicle {
var speed: Double { get set }
func move()
}
protocol Flyable: Vehicle {
var altitude: Double { get set }
func takeOff()
}
نوعی که Flyable را میپذیرد باید الزامات هر دو پروتکل — هم Vehicle و هم Flyable — را برآورده کند. Swift از وراثت چندگانه پروتکلها پشتیبانی میکند: protocol A: B, C.
Protocol Composition — مکانیزمی که امکان تعیین این را میدهد که یک نوع باید همزمان با چندین پروتکل مطابقت داشته باشد، بدون ایجاد پروتکل ترکیبی جدید.
func render(_ item: Drawable & Animatable) {
item.draw(context: ...)
item.animate(duration: 0.3)
}
Composition (&) در پارامترهای تابع، متغیرها و محدودیتهای جنریک کار میکند. کامپایلر بررسی میکند که نوع ارسالی همزمان همه پروتکلها را برآورده میکند. Composition اغلب در SwiftUI استفاده میشود: some View — این یک generic با composition است.
Protocol Composition بر ایجاد سلسلهمراتب وراثت ارجحیت دارد: به جای protocol A: B, C میتوان مستقیماً B & C را پذیرفت. این انعطافپذیری میدهد و وابستگی را کاهش میدهد. Composition به ویژه در پارامترهای تابع و محدودیتهای جنریک راحت است، جایی که نیاز به ترکیب موقت الزامات بدون ایجاد پروتکل میانی است. این تعداد انواع کمکی در کد را کاهش میدهد.
Protocol میتواند به عنوان نوع متغیر، پارامتر تابع یا عنصر مجموعه استفاده شود. این existential type نامیده میشود.
var drawableItem: Drawable
let items: [Drawable] = [Circle(...), Rectangle(...)]
func process(drawables: [any Drawable]) {
for item in drawables {
item.draw(context: ...)
}
}
کلمه کلیدی any (Swift 5.6+) به صراحت existential را نشان میدهد. بدون any کامپایلر اخطار میدهد. Swift همچنین از some (opaque types) برای پنهان کردن نوع مشخص در پشت پروتکل پشتیبانی میکند — این تکنیک استاندارد در SwiftUI است.
هنگام کار با protocol، توسعهدهندگان اغلب چندین اشتباه تکراری مرتکب میشوند.
Drawable به جای <T: Drawable> در جایی که نوع مشخصی نیاز استAnyObject بدون نیاز، که struct و enum را حذف میکندسوالات متداول
Protocol فقط الزامات را بدون پیادهسازی تعریف میکند (تا قبل از protocol extensions). Abstract class میتواند پیادهسازی و حالت داشته باشد. در Swift کلاسهای انتزاعی وجود ندارند — نقش آنها را پروتکلها با extensions ایفا میکنند.
بله، ساختارها، کلاسها و enum — همه میتوانند پروتکلها را بپذیرند. این اساس POP است: شما مجبور به استفاده از کلاسها برای سازماندهی معماری نیستید. ساختارها با پروتکلها معناشناسی مقدار و تغییرناپذیری را فراهم میکنند.
Associated type (associatedtype) — placeholder برای نوعی است که نوع پیادهکننده خودش تعیین میکند. مثال: Collection دارای associatedtype Element است. این generic در سطح پروتکل است.
بله، وراثت از AnyObject اضافه کنید: protocol MyProtocol: AnyObject. در این صورت فقط کلاسها میتوانند این پروتکل را بپذیرند. این برای مراجع weak و delegateها مفید است.
از is برای بررسی و as? برای تبدیل استفاده کنید: if let drawable = item as? Drawable. این فقط برای پروتکلهای بدون associated types کار میکند.
خلاصه
&) پروتکلها را بدون وراثت ترکیب میکندany) و opaque types (some) — دو روش کار با پروتکلهاما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.