Protocol — مجموعهای از الزامات (ویژگیها و متدها) است که تایپ پیادهکننده این پروتکل باید از آنها پیروی کند. در Swift، پروتکلها عنصر مرکزی Protocol-Oriented Programming (POP) هستند که پلیمورفیسم را بدون وراثت امکانپذیر میکنند. بر اساس دادههای Swift.org (2025)، پروتکلها در ۸۵٪ تایپهای کتابخانه استاندارد Swift استفاده میشوند. در Objective-C، @protocol نقشی مشابه دارد اما با محدودیت — فقط برای کلاسها.
نکات کلیدی
Protocol در Swift — یک اینترفیس انتزاعی است که الزاماتی را که یک تایپ باید برآورده کند تعریف میکند. پروتکل میتواند ویژگیها (با getter/setter)، متدها (نمونه و تایپ)، مقداردهندهها و subscript را الزام کند. برخلاف کلاسها، پروتکلها میتوانند توسط structها، enumها و classها پیادهسازی شوند — این انعطافپذیری را فراهم میکند که در زبانهای صرفاً کلاسمحور در دسترس نیست.
protocol Drawable {
var boundingRect: CGRect { get }
mutating func draw(in context: CGContext)
}
struct Circle: Drawable {
var center: CGPoint
var radius: CGFloat
var boundingRect: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
func draw(in context: CGContext) {
context.addEllipse(in: boundingRect)
}
}struct Circle پروتکل Drawable را پیادهسازی میکند و ویژگی boundingRect و متد draw(in:) را ارائه میدهد. به لطف پروتکل، هر شکلی که Drawable را پیادهسازی کند میتواند به صورت یکپارچه پردازش شود — این پلیمورفیسم بدون وراثت از یک کلاس پایه مشترک است.
Protocol-Oriented Programming (POP) — پارادایمی است که توسط Apple در WWDC 2015 به عنوان جایگزینی برای وراثت کلاسی ارائه شد. در POP، پروتکلها ابزار اصلی انتزاع هستند و توسعهدهندههای پروتکل (protocol extensions) پیادهسازی پیشفرض را ارائه میدهند. این کار مشکل «وراثت لوزی» را حل میکند و امکان توسعه تایپهای موجود بدون تغییر کد منبع را فراهم میکند.
| جنبه | POP (Protocol-Oriented) | OOP (Class-based) |
|---|---|---|
| واحد انتزاع | Protocol | کلاس پایه |
| استفاده مجدد | Protocol extension | وراثت |
| Value types | پشتیبانی میشود (struct) | فقط reference types |
| کاربرد چندگانه | Protocol composition | وراثت چندگانه (نه در Swift) |
| ریسک وابستگی | کم (اتصال ضعیف) | زیاد (سلسلهمراتب سفت و سخت) |
بر اساس وبلاگ Apple Swift (2025)، structها ۷۰٪ تایپها را در برنامههای مدرن Swift تشکیل میدهند. POP دلیل اصلی این تغییر است: پروتکلها به structها اجازه میدهند بدون انتقال به کلاسها رفتار پلیمورفیک داشته باشند.
پروتکلهای Swift موقعیت میانی بین اینترفیسهای Java و کلاسهای انتزاعی C++ را اشغال میکنند. آنها میتوانند پیادهسازی داشته باشند (از طریق extension)، اما حالت (ویژگیهای ذخیرهشده) ندارند. تفاوتها را با مثال سه زبان بررسی میکنیم.
| ویژگی | Swift Protocol | Java Interface | C++ Abstract Class |
|---|---|---|---|
| پیادهسازی متدها | بله (extension) | بله (default methods) | بله |
| ویژگیهای ذخیرهشده | خیر | خیر | بله |
| Value types | بله | خیر | خیر |
| پیادهسازی چندگانه | بله | بله | بله |
| مقداردهندهها | بله (الزامات) | خیر | بله |
تفاوت کلیدی: Swift Protocol میتواند مقداردهندهها و subscript را الزام کند که در Java Interface در دسترس نیست. در عین حال پروتکل نمیتواند حالت را ذخیره کند — این وظیفه تایپ پیادهکننده پروتکل است.
Associated Type (تایپ مرتبط) — یک تایپ عمومی درون پروتکل است که توسط تایپ پیادهکننده مشخص میشود. این امکان ایجاد پروتکلهای type-safe را بدون تعیین تایپ داده خاص فراهم میکند. تایپهای مرتبط با جنریکهای Swift کار میکنند.
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
var items: [Int] = []
var count: Int { items.count }
typealias Item = Int
mutating func append(_ item: Int) {
items.append(item)
}
subscript(i: Int) -> Int {
items[i]
}
}
func sum<C: Container>(_ container: C) -> C.Item where C.Item: Numeric {
// بدنه تابع
}Container — پروتکلی با associatedtype Item. IntStack آن را پیادهسازی میکند و typealias Item = Int را مشخص میکند. تابع جنریک sum از where-محدودیت برای کار فقط با کانتینرهای عددی استفاده میکند. Associated types پروتکلها را بدون از دست دادن type-safety عمومی میکنند.
Protocol composition — ترکیب چند پروتکل با عملگر &. تایپ منطبق بر ترکیب باید تمام پروتکلهای ترکیبشده را پیادهسازی کند. این جایگزین وراثت چندگانه میشود که در Swift وجود ندارد و امکان مشخص کردن دقیق الزامات پارامترهای تابع را فراهم میکند.
protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }
struct Person: Named, Aged {
let name: String
let age: Int
}
func greet(_ entity: Named & Aged) {
print("سلام، \(entity.name)، سن \(entity.age)!")
}
// Protocol extension — پیادهسازی پیشفرض
extension Named {
func introduce() {
print("اسم من \(name)")
}
}Protocol extension پیادهسازی پیشفرض متدها را فراهم میکند. تایپ پیادهکننده پروتکل میتواند متد extension را بازنویسی کند — در این صورت پیادهسازی خودش فراخوانی میشود. این مکانیزمی است که Swift با آن متدهای اختیاری را بدون @objc پیادهسازی میکند.
@protocol در Objective-C — predecessor پروتکل Swift است، اما با محدودیتهای قابل توجه. پروتکلهای Objective-C فقط برای کلاسها در دسترس هستند (نه برای structها یا enumها) و از ارسال پویا از طریق message passing استفاده میکنند. متدها میتوانند @required (پیشفرض) یا @optional باشند.
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end
@interface ConsoleLogger : NSObject
@end
@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
NSLog(@"[LOG] %@", message);
}
@endبرخلاف Swift، پروتکلهای Objective-C از associated types, generics, protocol extensions و value types پشتیبانی نمیکنند. آنها مکانیزم انتزاع کلاسی باقی میمانند، در حالی که Swift Protocol یک ابزار تمامعیار پلیمورفیسم برای همه تایپها است.
سوالات متداول
Protocol نمیتواند حالت (ویژگیهای ذخیرهشده) را نگه دارد — فقط الزامات مربوط به ویژگیها. Abstract class میتواند فیلدهای دارای داده داشته باشد. Protocol میتواند توسط structها و enumها پیادهسازی شود، abstract class — فقط توسط کلاسها. در Swift پروتکلها ابزار اصلی انتزاع هستند، کلاسها کمتر استفاده میشوند.
POP — پارادایمی که در آن پروتکلها و توسعهدهندههای پروتکل جایگزین سلسلهمراتب عمیق وراثت میشوند. به جای کلاس پایهای که همه زیرکلاسها از آن ارث میبرند، POP از ترکیب پروتکلها با پیادهسازیهای پیشفرض از طریق extension استفاده میکند. این کار وابستگی را کاهش داده و استفاده مجدد از کد را افزایش میدهد.
بله، پروتکلهای Swift از وراثت پشتیبانی میکنند. protocol SerializableDrawable: Drawable, Codable — پروتکلی که الزامات Drawable و Codable را ترکیب میکند. تایپ پیادهکننده SerializableDrawable باید الزامات همه پروتکلهای سلسلهمراتب را برآورده کند. این با وراثت کلاس متفاوت است — پروتکلها جد مشترکی ندارند.
some (opaque type) تضمین میکند که تابع یک تایپ خاص منطبق بر پروتکل را برمیگرداند. any (existential type) امکان ذخیره هر تایپ منطبق بر پروتکل را فراهم میکند. some برای حفظ هویت تایپ استفاده میشود، any — برای مجموعههای ناهمگن. some در Swift 5.1 ظاهر شد، any — در Swift 5.7.
از is برای بررسی و as? برای تبدیل استفاده کنید: if let drawable = object as? Drawable { drawable.draw(in: ctx) }. در Objective-C از conformsToProtocol: استفاده میشود. Swift همچنین is-بررسی را برای پروتکلهای بدون associated types پشتیبانی میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید