مفهوم Closure در سوئیفت

زمان مطالعه : ۴ دقیقه
آخرین بروزرسانی : ۱۵ آذر ۱۴۰۳
مفهوم closure در زبان برنامه نویسی سوئیفت و ارتباط آن با تابع ها

لازمه که اگر مبحث تابع ها را فراموش کرده اید، قبل از خواندن این مقاله، مقاله ی تابع ها را مرور کنید.

Closure چیست؟

Closure در Swift، بلاک ‌هایی از کد هستند که می‌ توانند در یک متغیر ذخیره شده و در نقاط مختلف برنامه فراخوانی شوند.

برای مثال شما در متغیر های از نوع String رشته میریزید، در Closure میتوانید چند خط کد قرار دهید.

از آن جایی که Closure ها درون خود چندین خط کد را ذخیره میکنند، میتوان آن ها را تا حدی شبیه به function ها در نظر گرفت.

تعریف Closure در Swift

تعریف closure ممکن است یک مقدار گمراه کننده باشد، برای همین با یک مثال بسیار ساده شروع میکنیم.

let closure = {
    print("Hello World")
}

حال برای استفاده از closure بالا به این شکل عمل میکنیم:

closure()

خروجی:

Hello World

تعریف Closure با پارامتر ورودی

مثل تابع ها، در بعضی موارد نیاز داریم که متغیری را به کلوژر پاس دهیم، در اینصورت به روش زیر عمل میکنیم:

let message = { (name: String) in
    print("I'm trying to learn \(name) ")
}
message("Swift.")

خروجی:

I'm trying to learn Swift

توضیحات بیشتر:

کلمه‌ی کلیدی in نشان‌ دهنده‌ی جدا کردن پارامترها و نوع خروجی از بدنه‌ی کد است.

تعریف Closure با مقدار خروجی

مثل تابع ها این امکان را داریم که بعد از انجام محاسبات مقداری را return کنیم.

let kelvin = { (celsius: Double) -> (Double) in
    let temp = celsius + 273
    return temp
}
kelvin(100) // 373
توضیحات بیشتر:
  • در closure ها بر خلاف function ها، نیازی به نوشتن نام پارامتر ورودی نیست (موقع صدا زدن kelvin درون آن celsius: را ننوشتیم.)

Closure به عنوان ورودی تابع

یکی از رایج‌ ترین کاربردهای closure، ارسال آن به توابع دیگر است.

به مثال زیر توجه کنید:

let add = { (a: Int, b: Int) -> (Int) in
    return a + b
}

let sub = { (a: Int, b: Int) -> (Int) in
    return a - b
}

func perform(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int {

    return operation(firstNumber, secondNumber)

}

// example add
perform(a: 273, b: 27, operation: add)

// example sub
perform(a: 273, b: 27, operation: sub)

خروجی:

300

246

مثال دیگر:

func filterNumbers(numbers: [Int], condition: (Int) -> Bool) -> [Int] {
    var filteredNumbers: [Int] = []
    for number in numbers {
        if condition(number) {
            filteredNumbers.append(number)
        }
    }
    return filteredNumbers
}

توضیحات بیشتر:

یک تابع به اسم filterNumbers داریم که دو پارامتر به عنوان ورودی میگیرد. ورودی اول آرایه ای از اعداد صحیح و ورودی دوم یک کلژر است.
هدف این است که بجای کلژر فیلتر های متفاوتی پاس دهیم. برای مثال یک کلژر برای فیلتر کردن اعداد زوج و یک کلژر برای فیلتر اعداد کمتر از ۵

به مثال زیر دقت کنید:

let numbs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// مثال اول: گرفتن اعداد زوج
let evenNumbers = filterNumbers(numbers: numbs) { number in
    return number % 2 == 0
}

// مثال دوم: گرفتن اعداد بزرگ تر از ۵ (از سینتکس کوتاه استفاده شده)
let greaterThan5 = filterNumbers(numbers: numbs) { $0 > 5 }

print(evenNumbers)
print(greaterThan5)

خروجی:

[2, 4, 6, 8, 10]
[6, 7, 8, 9, 10]
توضیحات بیشتر:
  • در مثال اول، پارامتر اول تابع که یک آرایه است را به کلژر (که خود پارامتر تابع است) پاس میدهیم و زوج بودن عدد را چک میکنیم.
  • در مثال دوم از سینتکس کوتاه کلژر استفاده کردیم.
  • علامت $0 به ورودی اول کلژر اشاره دارد.

تفاوت های Function و Closure در Swift

تابع ها و کلژر ها تا حده بسیار زیادی مشابه به هم هستند. ولی برخی تفاوت ها وجود دارد که به آن اشاره میکنیم

  1. توابع معمولاً برای عملیات ‌های عمومی و قابل استفاده مجدد تعریف می‌شوند.
  2. کلژر یک بلوک از کد است که می‌ تواند درجا تعریف شود و در هر جایی از کد استفاده شود.
  3. توابع همیشه یک نام دارند و در سطح فایل یا کلاس تعریف می‌شوند.
  4. توابع نمی ‌توانند بدون تعریف اولیه فراخوانی شوند.
  5. کلژر ها سینتکس کوتاه ‌تری نسبت به توابع دارند.
  6. در کلژر ها نیازی به نوشتن نام پارامتر ورودی نیست.
میلاد خط شب
میلاد خط شب
معتقدم هر آدمی میتواند در یک زمینه ای مفید و تاثیر گذار باشد و اصولا آدم "غیر مفید" نداریم. فقط کافی است به موقع و صحیح راهنمایی شود.
پاسخ دهید