رفتن به مطلب
مرجع رسمی سی‌پلاس‌پلاس ایران

پست های پیشنهاد شده

آموزش زبان برنامه‌نویسی سوئیفت - جلسه اول 

مواردی که در این جلسه یاد خواهید گرفت: مقدمه زبان برنامه‌نویسی سوئیفت ، نوشتن اولین دستور و معرفی متغییر‌ها

با سلام و عرض ادب خدمت شما دوستان عزیز و همراهان خوب همیشگی وب‌سایت آیوٌ اِسترِیم. در خدمت شما هستیم با یک دورهٔ جذاب برنامه‌نویسی به زبان سوئیفت! علاقه‌مندان زیادی به توسعهٔ محصولات و نرم‌افزار‌های شرکت اَپل وجود دارن و از این رو با مسائلی دست به گریبان هستند که یکی از آن‌ها؛ نبود آموزش کامل و به بیانی ساده است! مورد دوم هم که خیلی واضح هست،تَحریمه! که به جز اینکه قِشر کم‌درآمد جامعه از پس خرید آن‌ها بر نمی‌آیند، شامل تحریم‌های دیگر هم می‌شود‌. و خیلی‌ها بخاطر علاقه به یادگیری نمی‌توانند شروع کنند به توسعهٔ محصولات نرم‌افزاری شگفت‌اَنگیز! از این رو تنها یک راه وجود داره و آن هم استفاده از نسخهٔ هَک‌شدهٔ سیستم عامل مَک هستش که به شما امکان استفاده از امکانات یک سیستم‌عامل مَک واقعی را می‌دهد! البته هدف این نیست که بگوییم استفاده از این روش خوب هست! بلکه برای آن دسته از عزیزانی که توانایی خریدن محصولات اَپل رو ندارند گفتیم که در غیر این‌صورت اگه توانایی خرید دارید که بهترین راهش همین است  که بخرید و لذت یک سیستم‌عامل متفاوت و جدید را داشته باشید :). 

خُب،‌ اصل مطلب! اینکه در این دورهٔ آموزشی چه چیز‌هایی را یاد خواهید گرفت، فقط و فقط سه چیز است؛ 

  1. مقدمات یادگیری Syntax ( سِینتَکس) زبان و کدنویسی مقدماتی 
  2. یادگیری ‌رابط‌کاربری ( User Interface ) 
  3. ایجاد یک پروژهٔ ساده ماشین‌حساب 

و بعد از این مباحث هم کُلیت کار دستتان می‌آید و به راحتی ‌می‌توانید از منابعی مُعتبر،‌ دانش و مهارت خودتان را بالا ببرید. 

زبان برنامه‌نویسی سوئیفت ( Swift ) چیست ؟

سوئیفت یک زبان‌ برنامه‌نویسی از نوع کامپایلری برای توسعه محصولات نرم‌افزاری macOS , iOS , watchOS و tvOS است که توسط شرکت اَپل ساخته شده. قبل از این از زبان برنامه‌نویسی Objective-C برای توسعه محصولات برای موارد ذِکر شده استفاده می‌شد که بعد از آن این زبان جایش را به سوئیفت داد اما همچنان از Objective-C هم استفاده می‌شود. هدف در اینجا آموزش زبان است و شما می‌توانید برای توضیحات بیشتر به مرجع این زبان، اینجا مراجعه کنید. 

شروع کد‌نویسی

برای شروع کدنویسی به زبان‌برنامه‌نویسی سوئیفت می‌تونید از یک برنامه‌ موبایل هم حتی استفاده کنید! البته تنها در بخش مقدماتی. نام این نرم‌افزار موبایلی Sedona Swift Compiler است که می‌توانید از فروشگاه Play دانلود و نصب کنید. یا از نرم‌افزار‌ی ساده بر روی ویندوز خود کُد‌نویسی را شروع کنید که این کار برای سیستم‌عام‌ لینوکس هم صِدق می‌کند که با نصب یک بسته می‌توانید در لینوکس هم کُد‌نویسی با این زبان شیرین و ساده را شروع کنید. یا در نهایت اگر سیستم‌عامل مک دارید که چه بهتر و اگر ندارید از نسخهٔ هک‌شدهٔ آن استفاده کنید که عرض کردیم در مواقعی که واقعا چاره‌ای ندارید!( الخصوص برای بخش رابط کاربری ( User Interface ) ). 

اولین چیز در هر زبان برنامه‌نویسی که آموزش داده می‌شود؛ سلام جهان! (‌ !Hello World ) همیشگی است?!. پس این کُد ساده را ببینید که این پیغام را به راحتی در کنسول چاپ می‌کند:‌

print("Hello World!")

به همین سادگی که مشاهده کردید، با استفاده از متد print پیغام Hello World را چاپ کردیم. اگر این دستور رو اجرا کنید، با همین پیغام در کنسول  ویرایش‌گر خود مواجه می‌شوید. پس در نتیجه، این تابع برای چاپ مقادیر در سوئیفت هست. شاید دقت کرده باشید که سِمی‌کالُن نذاشتیم! سوئیفت این اجازه‌ رو می‌دهد که بدون گذاشتن سِمی‌کالُن برنامه‌‌ی خودتان را اجرا کنید که البته بگذارید هم مسئله‌ای پیش نمی‌آید، مگر در موقعی که چندین دستور در یک خط داشته باشید که آن موقع واجب می‌شود و باید حتما بگذارید، وگرنه کامپایلر اخطار خواهد داد! تابع print یک تابع سراسری در سوئیفت است که چندین آرگومانت دریافت می‌کند و اساس کار آن، چاپ اطلاعاتی است که به آن می‌دهیم. و چندین آرگومانت‌های پیش‌فرض‌ هم دریافت می‌کند که می‌توانیم بسته به نیاز از آن‌ها استفاده کنیم. 

در اولین آرگومانت، ما می‌توانیم تا هر چند‌ مقدار یا همان آیتم‌ها، به آن بدهیم و در خروجی نمایش دهیم. به این شکل که می‌بینید:

print("www.iostream.ir", "www.fanoox.com", item3, item4, ...)

در آرگومانت دوم، که separator است، می‌توانیم مشخص کنیم که اگر اطلاعات زیادی می‌خواهیم به خروجی ارسال و یا همان نمایش دهیم، در بین هر کدام از این اطلاعات، چه نمادی/علامتی قرار گیرد؟. که ما می‌تونیم اون نماد/علامت رو در بین دو "" ( دابل کوتیشن ) مشخص کنیم. به عنوان مثال:‌

print("www.iostream.ir", "www.fanoox.com", separator : " :)) ") // Output the ==> www.iostream.ir :)) www.fanoox.com

هما‌نطور که مشاهده کردید، می‌توانیم از هر نماد/علامتی که نیاز داشتیم در بین انبوهی از داده‌ها استفاده کنیم. 

در آرگومانت سوم، می‌توانیم مشخص کنیم که اطلاعات در خط بعدی ( New line ) چاپ شوند یا در همان خط فعلی نمایش داده شوند! که به صورت زیر است:

print("www.iostream.ir", terminator : "")
print("www.fanoox.com")
/*Output the => www.iostream.ir www.fanoox.com 
that not of include is new line */

در حالت پیش‌فرض تابع به صورت "terminator : "\n است که به معنی " در  در پایان چاپ اطلاعات، اطلاعات دیگر را که بعد از این مقادیر چاپ‌شده می‌آیند را چاپ کن ". 

 

 برای تعریف متغییر در سوئیفت به دو صورت می‌توانید عمل کنید:

  1. تعریف بدون تعیین نوع 
  2. تعریف با تعیین نوع 

همچنین ما دو نوع متغییر داریم:

  1. متغییری که مقدارش می‌تواند در ادامهٔ برنامه تغییر کند
  2. متغییری که مقدارش فقط در هنگام تعریف مشخص و قابل تغییر در سراسر برنامه نیست ( ثابت‌ها )

برای تعریف متغییر بدون نوع به این صورت عمل می‌کنیم:‌

var website_name = "www.iostream.ir"
print(website_name) // or print("The website name is \(website_name)")

همانطور که مشاهده می‌کنید تعریف یک متغییر که همواره مقدارش تغییر کنید با کلمهٔ کلید var تعریف می‌شود و بعد از آن نام و مقدار آن می‌آید. در این حالت کامپایلر به صورت ضمنی خودش از روی مقدار، نوع متغییر را متوجه می‌شود و اگر شما این دستور را بنویسید

var website_name = "www.iostream.ir"
print(type(of : website_name )) // or print("Type is => \(type(of : website_name )") 
// Result => String 

به شما مقدار  String یا همان رشته‌ای را نمایش می‌دهد. اما در حالت تعیین نوع برای متغییر به این صورت است:

var website_name : String = "www.iostream.ir"
print(webiste_name) // or print("The website_name is \(website_name)")

که شما صراحتا ( دستی ) نوع را مشخص کردید و کامپایلر در اینجا و در ادامهٔ برنامهٔ مقدار غیری از String ( رشته )  را قبول نمی‌کند. همان‌طور که مشاهده می‌‌کنید،‌ برای تعریف نوع برای متغییر باید از دو کالُن ( : )‌ استفاده کنید و سپس حرف اول نوع متغییر را بزرگ بنویسم ( البته در این زبان ) مانند؛‌  Int و سپس با گذاشتن علامت انتساب ( = ) مقدار مورد نظر خود را به آن اختصاص دهیم. نکته‌ای دیگری که وجود دارد در چاپ کردن مقادیر است که شما می‌توانید با دو روش فوق که ذکر شده‌ است، مقادیر را چاپ کنید که یکی بصورت آیتم به آیتم یعنی print( item1, item2, item3 , ...) و تا هر چند آیتم را که حاوی مقادیر هستند به خروجی بفرستید و نمایش دهید و اما در حالت دوم باید  Syntax متفاوتی استفاده کنید و آن هم ادغام رشته با مقادیر متغییر‌هاست! که مثالش را بالا برای شما عزیزان زده‌ام و مقادیر متغییر‌ها باید بین دو پرانتز و قبل پرانتز از یک بک‌اسلش رو به عقب استفاده کنید!‌.  و اما برویم به سراغ ثابت‌‌ها! از اسم این متغییر‌ها واضح است که یک بار تعریف می‌شوند و مقدار ثابتی دریافت می‌کنند و در ادامهٔ برنامه و یا رَوند پروژه هیج تغییری نمی‌کنند و در طول برنامه یا پروژه مقادیرشان ثابت است! بیاید با یک مثال شروع کنیم؛ ثابت‌ها در سوئیفت با کلمهٔ کلید let تعریف می‌شوند و همانند متغییر‌ها شامل نام و نوع هم هستند: 

let _website_name = "www.iostream.ir"
_webiste_name = "iostream.ir" // Error , beacuse it's a constant  
print(_website_name) // or print("The website name => \(_website_name)")

هما‌نطور که می‌بینید، تغییر دادن مقادیر ثابت‌ها باعث بروز خطا می‌شود و اجازهٔ چنین کاری به شما داده نخواهد شد.  برای تعریف با تعیین نوع هم به این شکل می‌توایند عمل می‌کنید:

let _number : Int = 20
_number = 40 // Error , beacuse it's a constant  
print(_number) // or print("The number => \(_number)")

 امیدواریم این جلسه مورد رضایت شما عزیزان قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه دوم

مواردی که در این جلسه یاد خواهید گرفت: نحوهٔ نام‌گذاری متغییر‌ها ، نام‌گذاری صحیح و مجاز متغییر‌ها و دستورات شرطی

در ای جلسه، شما با نحوه نام‌گذاری صحیح متغییر‌ها، دستورات شرطی و حلقه‌ها آشنا خواهید شد و بعد از آن باید تمرین کنید که ریز به ریز همه‌چیز را متوجه شوید و این را بدانید که هر مطلبی را که باید برای بهتر کردن مهارت‌های خودتون مطالعه کنید و عمل نکنید، در واقع هم به زودی مطلب از ذهنتان پاک خواهد شد و همچنین این‌که وقت و انرژی شما گرفته می‌شود خُب، برویم که وقت شما عزیزان  از این بیش‌تر تلف نشود و آموزش را شروع کنیم.

نحوهٔ نام‌گذاری صحیح متغییر‌ها 

نحوهٔ نام‌گذاری متغییر‌ها در هر پروژهٔ نرم‌افزاری از اهمیت زیادی برخوردار است! چرا که هم پروژهٔ شما بر روی نظم و قانون  پیش خواهد رفت و هم این که اگر روزی خودتان یا توسعه‌دهنده‌‌‌ای دیگر قصد داشت در توسعهٔ پروژه با شما همکاری کند، با دیدن نام‌های عجیب و غریب متغییر‌ها روبرو نشود! و نداند هر کدام از این متغییر‌ها کجا استفاده می‌شوند! حالا جدا از اینکه یک‌سری استاندارد‌ها دیگر هم در کدنویسی باید رعایت شود (‌ کُد تَمیز )‌ که دیگر بستگی به خود شما و تجربه‌‌ای دارد که شما کسب کردید. 

نکته‌ها:

  • نام‌گذاری کارکتر‌ها شامل تمامی کارکتر‌های یونیکد ( کارکتر‌های مجاز )‌ است. مانند ( ? یا ? و ایمُوجی‌های دیگر ) می‌باشد.
  • نام متغییر‌ها و ثابت‌ها نمی‌توانند شامل فضای خالی ( " " )، نماده‌های ریاضی ( +,-,/ و .. )، علامت‌‌ها ( {}.(),&,^ و .. ) و کارکتر‌های غیر‌مجاز باشند.

سه تا از معروفت‌ترین و پرکاربردترین نگار‌ش‌ها در برنامه‌نویسی و نام‌گذاری متغییر:‌

  • نگارش شُتری ( camelCase )
  • نگارش پاسکال ( PascalCase )
  • نگارش ماری ( snake_case ) 

این سه از پرکاربرترین سبک‌های نگارش در زبان برنامه‌نویسی و نام‌گذاری آن‌ها هستند. البته نگارش‌های دیگری هم هستند که همونطور که گفتیم، این سه، جز پرکاربردترین و معروفت‌ترین‌ها هستند که البته به شَخصه نگارش ماری را بیشتر دوست خواهم داشت! برویم و یک مثال از هر کدام بزنیم؛

نگارش شُتری ( camelCase )

var webSite = "www.iostream.ir" // Or with type var webSite : String = "www.iostream.ir"
print(webSite)
// Also the constant 
let webName = "www.iostream.ir" // Or with type let webName : String = "www.iostream.ir"
print(webName)

دقت کنید که حرف اول کلمه باید کوچک باشد و حرف دوم از کلمهٔ دوم بزرگ و سومین کلمه بازم بزرگ و همین‌طور تا آخر... و فقط حرف اول مورد هدف برای کوچک بودن در نظر گرفته می‌شود. 

نگارش پاسکال ( PascalCase )

var WebSite = "www.iostream.ir" // Or with type var WebSite : String = "www.iostream.ir" 
print(WebSite)
// Also the constant 
let WebName = "www.iostream.ir" // Or with type let WebName : String = "www.iostream.ir"
print(WebName)

در این نگارش هم همان‌طور که مشاهده می‌کنید، حرف اول دوم و الی آخر ... هر کلمه باید بزرگ باشد.

نگارش کبابی ( snake_case ) کباب به سبک برنامه‌نویسی?! 

var web_site = "www.iostream.ir" // Or with type var web_site : String = "www.iostream.ir" 
print(web_site)
// Also the constant 
let _web_name = "www.iostream.ir" // Or with type let web_name : String = "www.iostream.ir"
print(_web_name)

توی این نگارش، نام‌ متغییر‌ها اگر دارای چندین کلمه‌ باشند باید توسط یک آندرِلاین ( ـ ) ( دقت کنید که با علامت ( - ) متفاوت است ) از یک دیگر جدا می‌شوند و همچنین باید با حروف کوچک نوشته شوند. 

اگر دقت کرده باشید، متوجه شده‌اید که ما از نام‌های بی‌ربط و گیج‌کننده استفاده نکرده‌ایم! بطور مثال هر کسی با دیدن متغییری با نام web_site متوجه خواهد شد که این متغییر مربوط به داده‌های وب‌سایت است که می‌توانست به این شکل باشد،   w , x , we  و این‌گونه نام‌ها که گیج‌کننده هستند. حتی مثال بالا (‌ web_site ) می‌توانست بهتر از این نیز باشد،  web_site_iostream که هر چقدر نام‌های متغییر‌ واضح‌تر و اصولی‌تر باشد، خوانایی کد‌های شما و استاندارد پروژهٔ شما بالا می‌رود که البته کار اول را که درست انجام بدهید، باقی کار‌ها هم بر  روی استانداد‌های اصولی پیش می‌رود! البته این نظر خود بنده هستش?. ( خِشت اول که  نهَد معمار کَج، تا ثُریا رَود دیوار کج! ) 

دستورات شرطی 

 اگر وجود دستورات شرطی نباشند فقط می‌توانیم یه برنامهٔ کوچک بنویسیم! در واقع یه برنامهٔ ساده و در حد چاپ اطلاعات و دستوراتی در همین محور. اما در پروژه‌های بزرگ نبود دستورات شرطی یعنی عذاب برای یک برنامه‌نویس!‌‌ یه توضیح کوتاه دربارهٔ این موضوع بدهیم و سپس شروع به کد‌نویسی می‌کنیم که البته این دوره بر این مبنا شروع شده که شما اطلاعات پایه‌ای از برنامه‌نویسی دارید و نیازی به توضیحات زیاد درمورد دستورات پایه ندارید. 

دستورات شرطی رو یک دو راهه در نظر بگیرید! اینکه یه تابلو زده شده است به سمت راست و نوشته که راه موفقیت شما از این طرفه و طرف دیگه نوشته این راه منجر به موفق نشدن شما می‌شود! حالا نوبت ذهن شماست که تصمیم بگیره کدام طرفی برود ( ذهن شما هم بر اساس باور‌های شما تصمیم می‌گیرد، یعنی از قبل برنامه‌ریزی شده است! ) مطمعنن کسی نمی‌خواد موفق نشود، اینطور نیست؟‌! پس دو راهه نقش شرط و ذهن شما نقش مترجم یا کامپایلر را بازی خواهد کرد با این تفاوت که ما حق انتخاب داریم اما در برنامه‌نویسی ما حق انتخاب را مشخص خواهیم کرد و کامپایلر همان چیزی را که ما صحیح می‌دانستیم و نوشتیم اجرا می‌کند. با این تعریف احتمالا متوجه شده باشید، پس برویم سراغ شرط دوست‌داشتنی ‌if!

 در زبان‌های مختلف، تعریف و استفاده از دستورات شرطی و یا سایر دستورات پایه تفاوت‌هایی با هم دارند و درمورد سوئیفت هم همین قانون صدق می‌کند! اینکه سوئیفت از سینتَکس ساده و  زیبایی برای تعریف دستورات استفاده می‌کند که با سایر زبان‌ها تفاوت‌های ریزی دارد! تعریف دستور ‌if در سوئیفت به این شکل است؛

var boolean : Bool = true
if boolean == true
{
   print(" Okay , This is boolean => \(boolean)")
}

در این تعریف همان‌طور که مشاهده می‌کنید، شرط if نیازی به پرانتز ندارد و فقط شرط جلوی آن قرار می‌گیرد و در صورت درست بودن ( true )  دستورات داخل بدنه ( {} ) اجرا خواهند شد. این نکته را هم در نظر داشته باشید بر خلاف زبان‌های دیگر، باید حتما اکولاد‌ها  ( {} ) را بگذارید حتی اگه فقط یک دستور باشد چرا که تعریف آن به همین شکل است.

اما اگر شرط برقرار نبود و بخواهیم دستور دیگری را اجرا کنیم، از else، دوست خوب if استفاده خواهیم کرد؛ 

var boolean : Bool = true
if boolean == true
{
   print(" Okay , This is boolean => \(boolean)")
}
else
{
   print(" This is not boolean! => \(boolean)")
}

در این قسمت اگر شرط اول برقرار نشد، یعنی boolean مقدارش false بود، else اجرا و پیغام This is not boolean به همراه مقدار متغییر boolean نمایش داده خواهد شد.  

در مواقعی هم می‌خواهیم چندین شرط داشته باشیم! یعنی که اگر شرط اول برقرار نبود، شرط دوم و اگر شرط دوم برقرار نبود شرط سوم و الی آخر .. که به این صورت عمل خواهیم کرد؛

let ـweb_site_name = "www.iostream.ir"
if web_site_name == "www.iostream.ir"
{
   print("This is web site => \(ـweb_site_name)")
}
else if ـweb_site_name == "www.google.com"
{
   print("This is not web site!")
}
else if ـweb_site_name == "www.microsoft.com"
{
   print("This is not web site!")
{
else 
{
    print("None")
}

به راحتی می‌توانید دستورات شرطی خودتان را تا بی‌نهایت (‌ مواقعی که مورد نیاز اس) گسترش دهید. 

 

 Switch یکی دیگر از دستور‌ات شرطی است که به مراتب، تمیز‌تر و خوانا‌تر از if و else است!

این دستور یک مقدار قبول دریافت می‌کند و بعد از آن توسط کِیس‌هایش ( case ) به بررسی آن‌ها و مطابقت بود یا نبودن مقدار اصلی با مقادیر موجود می‌پردازد. نحوهٔ تعریف آن به این شکل است که مشاهده می‌کنید؛ 

let web_site_name = "www.iostream.ir"
switch web_site_name 
{
  case "www.iostream.ir":
    print("This is web site => \(web_site_name)")
  case "www.google.com":
    print("This is not web site!") 
   .
   .
   .
   .
   default:
   print("None")
}

switch در اینجا نقش همان  if را بازی می‌کند با این تفاوت که بررسی‌ها در بدنه و توسط caseهایی که دارد صورت می‌گیرد که case اول می‌گوید؛ اگر متغییر web_site_name برابر مقدار www.iostream.ir بود،‌ چاپ کن؛ This is web site => web_site_name و به همین صورت caseهای دیگر که در صورتی که  case قبلی با مقدار موجود در switch برابر نبود، case بعدی اجرا خواهد شد و در آخر شما می‌توانید مانند دستور شرطی else  اگر هیچ‌کدام از شرط‌ها ( در اینجا caseها ) برقرار نبود، چاپ کند None یا هیچ‌کدام! این کار با استفاده از کلمهٔ کلیدی default صورت می‌گیرد، چیزی خارج از موارد تعریف شده ( case‌ها ) این مورد را اجرا خواهد کرد. 

امیدواریم که این جلسه مورد رضایت شما عزیزان قرار گرفته باشد. 

 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه سوم

مواردی که در این جلسه یاد خواهید گرفت: انواع داده و حلقه‌ها

 در زبان برنامه‌‌نویسی سوئیفت ما با انواعی از داده‌ها روبرو هستیم! طبق دیگر زبان‌های برنامه‌نویسی نوع داده‌های پرکاربرد را معرفی خواهیم کرد و همچنین دیگر نوع‌های داده را در ادامه بازگو می‌کنیم که شما با دقت بتوانید در پروژه‌های خودتان نوع‌های دادهٔ مناسب پروژهٔ خودتان را انتخاب کنید. همچنین باید در نظر داشته باشید که در هر پروژهٔ نرم‌افزاری به کار بردن نوع‌های داده‌‌ای که اصلا شاید مناسب قسمتی از پروژه یا نیازی به آن نباشد و با نوع داده‌ای دیگر مسئله بهتر و بهینه‌تر حل شود و استفاده کنید، استاندارد پروژهٔ شما کاهش پیدا خواهد کرد و مطمعن هستم که شما دوست ندارید نرم‌افزاری غیر‌استاندارد و بهینه داشته باشید! بنابراین  در انتخاب نوع‌های داده در پروژه‌های خودتان نهایت دقت را به خرج دهید! چه کسی دوست ندارد که پروژه‌ای کارآمد و بهینه داشته باشد که هر توسعه‌ دهنده‌ای با دیدن نظم و بهینه بودن پروژه‌اش، آن را تحَسین کند؟!. درمورد حلقه‌ها هم یک توضیح مختصر خواهیم داد و بعد به سراغ کُد‌نویسی خواهیم رفت که مطمئنن قسمت هیجانی برای هر برنامه‌نویسی است?

همهٔ ما در برنامه‌نویسی نیاز داریم که چندین خط کد رو بنویسم تا در نهایت برنامهٔ ما به خوبی اجرا شود، البته اگه بقیهٔ قسمت‌های کد‌هایتان به درستی کار کند! اما همین چند خط کد رو مثلا چاپ اعداد ۰ تا ۱۰ در نظر بگیرید؛ 

print(0)
print(1)
print(2)
print(3)
print(4)
print(5)
print(6)
print(7)
print(8)
print(9)
print(10)

احتمالا با خودتان می‌گوید چه برنامه‌نویسی داریم که چنین‌کاری می‌کند؟! این همه کد! حالا فکر کنید از ۰ تا ۱۰۰۰ باید به همین شکل بنویسید! کاری با خطوط کد‌ها و حتی منطقی‌ بودن آن هم نداریم! اما واقعا حوصله، زمان و انرژی باارزشتان چه می‌شود؟ پس راه‌حل چیست؟  درست حدس زدید! حلقه‌ها! این مسئله را به سادگی و زیبایی هر چه تمام‌ترحل کردند. پس مثال بالا را با یک حلقه می‌نویسیم؛

for index in 0...5
{
   print(index) // Output => 0,1,2,3,4,5
}

فقط با چندین خط کد این مسئله برطرف شد! حال شما می‌توانید به‌ جای عدد ۵، عدد ۱۰۰۰ یا بیشتر را قرار بدهید. پس متوجه شدید که کاربرد حلقه‌ها در برنامه‌نویسی چقدر مهم و حیاتی هستند! که برای تکرار دستوراتی هستند که داده‌های زیادی به صورت مستقیم یا غیر مستقیم در برنامه‌ مورد استفاده قرار می‌گیرد و عملا بدون حلقه‌ها باید کد‌های زیادی بنویسید تا این داده‌ها نمایش داده شوند!.

انواع داده

در سوئیفت، ما با انواعی از داده سر و کار داریم که عبارت‌اند از:

انواع دادهٔ صحیح و اعشاری

Int۸؛ نوع دادهٔ عددی ۸بیت است، به این صورت که فقط توانایی ‌ذخیره ۱‌بایت را دارد. و مقادیر ۱۲۷ تا ۱۲۷- را پوشش می‌دهد.

UInt8؛ این نوع داده عددی  فقط و فقط یک مقدار از ۰ تا ۲۵۵ را پوشش خواهد داد و ۱‌بایت است. که در واقع کوتاه‌ شدهٔ نام Unsigned Integer، است که به معنای نوع بدون علامت ( -‌ ) است.

Int۳۲؛  این نوع داده ۴‌بایتی (‌ ۴ *‌ ۸ ) است، و مقداری از ۲۱۴۷۴۸۳۶۴۷ تا ۲۱۴۷۴۸۳۶۴۷- را پوشش می‌دهد. 

UInt32؛ مانند UInt8، است، با این تفاوت که فقط مقادیر صحیح بدون علامت ( - ) را قبول می‌کند و ۴‌بایت است. از مقدار ۰ تا ۴۲۹۴۹۶۷۲۹۵ را پوشش می‌دهد. 

Int۶۴؛ ‌مقداری بیشتری در خود ذخیره می‌کند و در نتیجه تعداد بایت‌های بیشتری را هم از حافظه اشغال می‌کند! که ۸‌بایت است. یعنی اینکه مقدار عددی تا ۲۰ رقم عدد صحیح با علامت ( + ) و بدون علامت ( - ) را ذخیره می‌کند. از مقدار ۹۲۲۳۳۷۲۰۳۳۶۸۵۴۷۷۵۸۰۸ تا ۹۲۲۳۳۷۲۰۳۳۶۸۵۴۷۷۵۸۰۸- را پوشش می‌دهد. 

UInt۶۴؛ مانند Int64 است که مقدار بیشتری ذخیره می‌کند که فقط شامل اعداد صحیح بدون علامت ( - ) است و ۸‌بایتی. از مقدار ۰ تا ۱۸۴۴۶۷۴۴۰۷۳۷۰۹۵۵۱۶۱۵ را پوشش می‌دهد ( دو برابر Int64 ). 

Float: این نوع دادهٔ اعشاری است و ۴‌بایتی. مقادیر اعشاری از ۱.۲E-38 تا ۳.۴E-38 را پوشش می‌دهد ( تا ۶ رقم اعشار ). البته این اعدا و این نوع نوشتاری، نماد‌های علمی هستند!.

Double: در این نوع اعشاری یک تفاوت وجود دارد و آن  اینکه فضای بیشتری را در اختیارمان می‌گذارد و همین‌طور دقت بالایی را هم در محاسبات به همراه دارد. ۸‌بایتی است و از مقدار ۲.۳E-308 تا ۱.۷E+308 را پوشش می‌دهد ( تا ۱۵ رقم اعشار ).

برای هر کدام یک مثال خواهیم زد؛ 

var int_8_byte : Int8 = -50
print(int_8_byte)
var uint_8_byte : UInt8 = 50
print(uint_8_byte)
var int_32_byte : Int32 = -560
print(int_32_byte)
var uint_32_byte : UInt32 = 560
print(uint_32_byte)
var int_64_byte : Int64 = -1567
print(int_64_byte) 
var uint_64_byte : UInt64 = 1567
var float : Float = 18.5
print(float)
var double : Double = 19.75
print(double)

 این قطعه کد‌ها را در اِدیتور ( Editor ) یا IDE خودتان وارد و اجرا کنید تا نتیجه را بصورت زنده مشاهد کنید ( لطفا کُپی و پیست نکنید! ) خودتان بنویسید تا هم لذت کد‌نویسی را بچشید و هم این‌که بهتر یاد‌ بگیرید. در این میان، دقت کنید که نوع دادهٔ خودتان را به درستی در پروژه‌های نرم‌افزاری استفاده کنید و طبق نیاز نرم‌افزار خود از دادهٔ مورد نیاز استفاده کنید. به عنوان مثال، یک بخشی از برنامهٔ شما نیاز به داده‌ای به اندازهٔ ۸‌بایت دارد، ولی شما می‌آید و یک دادهٔ ۶۴‌بایتی تعریف می‌کنید برای آن! با این‌کار حافظهٔ سیستم شما و آن کسی که نرم‌افزار شما را اجرا خواهد کرد، احتمالا صدای فَن آن در خواهد آمد! پس دقت کنید. 

نوع دادهٔ بُولیَن ( Boolean )

 دو مقدار True یا False دریافت می‌کند. از این نوع داده بیشتر در دستورات شرطی استفاده می‌شود و بخش‌هایی از برنامه که نیاز به بررسی و درستی یا نادرستی یک عبارت دارد. نحوهٔ تعریف و استفاده از آن هم به این شکل است؛

let _boolean : Bool = true // Or false
print(_boolean)

در این تعریف شما می‌توانید با تعریف نوع دادهٔ Bool و سپس مقدار به آن، از آن در قسمت‌های مختلف برنامه استفاده کنید. 

نوع داده‌های رشته‌ای و کارکتری

String؛  یک دنباله‌ای از رشته ( همان متن ) را در خود ذخیره می‌کند؛

let _web_site_iostream : String = "www.iostream.ir"
print(_web_site_iostream)

Character؛ فقط و فقط یک کارکتر را قبول می‌کند( به جز کارکتر‌های کنترلی )؛ 

let _character : Character = "i"
let _character_control : Character = "\n"
print(_character) // Output => i
print(_character_control) // Output => new line

همان‌طور که مشاهده کردید، چندین نوع‌ داده‌ در زبان برنامه‌نویسی سوئیفت وجود دارد که شما باید با توجه به پروژهٔ خودتان از آن‌ها در جای مناسب استفاده کنید. 

حلقه‌ها و انواع آن 

حلقه‌ها در سوئیفت به طور متفاوتی تعریف می‌شوند، اما همهٔ آن‌ها کار یکسانی انجام می‌دهند! یعنی تکرار دستورات! حلقهٔ اول که قصد معرفی آن را داریم، for است؛ 

for index in 0...5
{
  print(index)
}

در این تعریف همان‌طور که مشاهده می‌کنید، با تعریف کلمهٔ کلید for و بعد از آن یک نام دلخواه و معنی‌دار، برای اینکه مقادیر هر بار در آن ذخیره شوند (‌ در واقع نقش یک متغییر را بازی می‌کند ) و بعد کلمهٔ کلید in قرار می‌گیرد و در نهایت باید یک رِنج ( بازه ) مشخص از یک عدد تا یک عدد دیگر انتخاب کنیم که بین این‌ها با سه نقط ( ...‌ )‌ از هم جدا می‌شوند! این به این معنی است که در این تعریف عدد اولی که تعیین می‌شود، تا عدد دوم به صورت کامل در ‌index ذخیره خواهند شد و هیچ گونه کم و زیادی صورت نمی‌گیرد!. 

اما اگر بخواهیم یک عدد کمتر و یا در واقع یک تکرار کم‌تر داشته باشیم از این تعریف استفاده می‌کنیم؛

for index in 0..<5
{
  print(index)
}

در این صورت با آپریتر > ( کوچک‌تر )  می‌توانیم یک عدد و در واقع یک تکرار کمتر داشته باشیم. 

اگر بخواهیم درمورد آرایه که در جلسات بعد دربارهٔ آن‌‌ها صحبت خواهیم کرد، یک مثال بزنیم، به این صورت است؛

let _array_number = [10,20,30,40]
for index in _array_number
{
 print(index)
}

 همان‌طور که می‌بینید، تعریف و استفاده از حلقهٔ for ساده و آسان است. 

حلقهٔ while، حلقهٔ دومی است که به معرفی آن خواهیم پراخت. این حلقه به این صورت تعریف خواهد شد؛‌ 

var number : Int8 = 0
while (number < 10)
{
  print(number)
  number += 1
}

در حلقه‌ و در قسمت شرط آن شما می‌توانید هر شرطی را که باعث ورود به بدنهٔ حلقه (‌ {} ) شود، تعریف کنید. کلمهٔ کلید while در ابتدا تعریف می‌شود و سپس شرطی را که مد‌نظرتان است، تعریف می‌کنید ( در بین دو پرانتز ) و سپس در بدنه شرط، دستورات خود را می‌نویسید. 

در نهایت، حلقهٔ آخر، حلقهٔ repeat استکه کارکردآن دقیقا همانند حلقهٔ do, while در سایر زبان‌های برنامه‌نویسی است! نحوهٔ تعریف و استفاده از آن هم به این شکل است؛

var repeat : Int8 = 0
repeat {
print(repeat)
  repeat += 1
} while repeat < 1

در این حلقه، بدنهٔ حلقه که شامل دستورات هستند ابتدا اجرا می‌شود و سپس شرط بررسی می‌شود! درست همانند do, while. این حلقه با کلمهٔ کلید repeat تعریف شده و سپس در بین آکولاد‌ها (‌ {} ) دستورات نوشته خواهند شد و بعد از آخرین آکولاد ( { ) جلوی آن و یا بعد آن کلمهٔ کلید while و سپس شرط را می‌نویسم. فقط توجه داشته باشید که while در اینجا نیازی به پرانتز ندارد!. البته این دستور فقط یک بار اجرا خواهد شد! چرا که متغییر repeat کوچکتر از ۱ نیست، بزرگتر از آن هم نیست و در واقع مساوی است ( مقدار repeat در همان ابتدا اول یک بار افزایش ( repeat =+ 1 ) داده می‌شود و مقدار ۱ را درون خود ذخیره می‌کند ). پس شرط نادرست ااست و حلقه دیگر اجرا نخواهد شد. 

نکته؛‌ دقت کنید که در تمامی حلقه‌ها نیاز به آکولاد باز و بسته برای تعریف دستورات است و شما نمی‌توانید بدون تعریف این آکولاد‌ها کدهای خودتان را بنویسید! پس این مورد را دقت کنید. به جزء حلقهٔ while دیگر حلقه‌ها نیازی به پرانتز () برای تعریف شروط ندارند.

امیدواریم که این جلسه هم مورد رضایت شما عزیزان قرار گرفته باشد. 

 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه چهارم

مواردی که در این جلسه یاد خواهید گرفت: کامنت‌ها، دو ویژگی نوع‌های داده Int، آپِریِتر‌ها ( Operators )، کلمات کلیدی break,continue,fallthrough

کامنت‌ها

در زبان برنامه‌نویسی سوئیفت مثل اکثر زبان‌های برنامه‌نویسی دیگر، از کامنت‌ها استفادهای زیادی می‌شود و معمولا برای اهدافی کامنت‌ها استفاده می‌شوند و می‌توانند شامل موارد زیر باشند:

  • برای غیر‌فعال کردن موقتی یک قسمت یا بخشی از کُد
  • برای توضیح دادن کدها برای دیگر برنامه‌نویسان یا توسعه‌دهندگان
  • یا توضیح کد برای اینکه در مراجعات بعدی به پروژه کارکرد همان قسمتی که کامنت کردید را متوجه شوید

انواع کامنت‌ها در زبان برنامه‌‌نویسی سوئیفت؛

  • تَک خطی (‌ single-line )
  • چند خطی ( multi-line )

در کامنت تک خطی، با گذاشتن دو علامت // می‌توانید توضیحات خود را فقط در همان خط درمورد کُد مورد نظر بنویسید و بعد از آن کامنت شما در واقع در حال تعریف دستور جدید هستید! این کامنت، به این صورت استفاده می‌شود؛

let _web_site_name : String = "www.iostream.ir"
print(_web_site_name) // Ouput the string of www.iostream.ir

 در مثال بالا همان‌طور که مشاهده می‌کنید از کامنت تک خطی استفاده کردیم، و بعد از این کامنت شما نمی‌توانید انتظار داشته باشید که در خط جدید دوباره حالت کامنت‌گذاری برای شما همچنان فعال باشد! چرا که در خط بعدی دستوری جدید داریم نه کامنتی ادامهٔ کامنت قبل!.

و اما کامنت چند خطی که می‌توانید در تعداد خط‌های بیشتر، توضیحات خود را بنویسید؛

let _web_site_name : String = "www.iostream.ir"
/* We can also use
from of
print("String.. and \(_web_site_name)") */
print(_web_site_name) 

در مثال بالا که مشاهده می‌کنید، شما هیچ محدودیتی برای اضافه کردن توضیحات بیشتر برای  خود کد‌های خود ندارید و تا هر چند خط توضیحات که مد‌نظرتان بود، می‌توانید استفاده کنید.

دو ویژگی نوع دادهٔ Int

 اگر بخواهیم کوچک‌ترین و بزرگ‌ترین عدد موجود از نوع دادهٔ Int را بدست آوریم، از دو ویژگی max,min استفاده می‌کنیم. هر دو ویژگی به همراه مثال در زیر آورده شده‌اند؛

print("Max => \(Int.max)") 
print("Min => \(Int.min)")

با اجرای کد‌های بالا،‌ بزرگترین مقدار موجود نوع دادهٔ  Int و همچنین کوچک‌ترین آن به شما نمایش داده خواهد شد.

آپِریِتر‌ها (‌ Operators )  

آپریترها در هر زبان برنامه‌نویسی به عنوان پایه و اساس محاسبات و در بعضی موارد برای کارهای دیگر استفاده می‌شوند. محاسباتی مانند، جمع، تفریق،تقسیم،ضرب و باقی مانده و ...

در سوئیفت این 8 دسته آپریتر وجود دارد:

  •  اِنتسابی ( Assigment Operator )
  • محاسباتی ( Arithmetic Oprerator ) 
  •  باقی‌مانده ( Remainder Operator ) 
  •  مُرکب ( Compound Assigment Operator ) 
  •  مقایسه‌ای ( Comparison Operators ) 
  •  ترِنِری ( Ternary Conditonal Operators )
  •  دامِنه ( Range Operator )
  •  منطقی ( Logical Operators )

این‌ها، کل آپریترها در سوئیفت هستند که هر کدام عمل مخصوص به خود را انجام می‌دهند. در مثال‌های زیر هر کدام از این‌ها را به همراه مثال برای شما آورده‌ایم.

آپریتر اِنتسابی ( Assigment Operator )

 اگر ما یک مقداری را به متغییری انتساب می‌دهیم، عملا داریم از آپِریِتر‌‌ انتساب ( = ) استفاده می‌کنیم. چرا که کدنویسی از سمت چپ شروع می‌شود و این هم کاملا منطقی هم است که مقدار دهی به یک متغییر از سمت چپ صورت می‌گیرد و مقدار سمت راست را درون خود ذخیره می‌کند. به این مثال دقت کنید؛ 

let _web_site_name : String = "www.iostream.ir"
   //  Assigment Operator ( = )
print("Type of \(type(of : _web_site_name ) and the website of name \(_web_site_name)")

 در مثال بالا مشاهده می‌کنید که مقدار www.iostream.ir که یک مقدار رشته‌ای/متنی است را در متغیر web_site_name ذخیره می‌کنیم. این کار با استفاده از این علامت ( = ) انجام شده است. 

در خط بعد هم نوع متغییر و مقدار موجود در متغییر web_site_name که ذخیره شده است را نمایش می‌دهیم.

آپریتر‌های محاسباتی ( Arithmetic Oprerator ) 

در قسمت‌هایی از پروژه پیش آمده که ما باید محاسباتی را انجام بدهیم. این کار با استفاده از این آپریتر‌ها انجام می‌شود. که شامل: +،-،/،* و ٪ هستند. 

برای هر کدام از این‌ها، مثال‌هایی در زیر آورده شده است؛

جمع ( + ) 

var number_one, number_two : Int8
number_one = 50 
number_two = 50
print("Result = > ", number_one + number_two) // Output the number 100

در مثال بالا همان طور که مشاهده می‌کنید، ابتدا دوم متغییر با نوع Int8 تعریف کرده‌ایم و سپس در خطوط بعد به آن‌ها مقادیر ۵۰ را داده‌ایم. در نهایت عمل جمع ( + ) را روی آن‌ها به صورت مستقیم انجام داده و نمایش می‌دهیم. یا اگر ساده‌تر بخواهیم تعریف کنیم، آپریتر ( + ) عمل جمع کردن اعداد و یا متصل کردن دو رشته را بر عهده دارند؛

var web_site_name, platform_name : String
web_site_name = " www.iostream.ir :)"
platform_name = " www.fanoox.com  ;)"
print("Binding two string => ", web_site_name + platform_name) // Ouput the website name and platform name => www.iostream.ir :) www.fanoox.com ;)

و به همین راحتی می‌توانید تا بی‌نهایت عمل جمع و متصل کردن رشته‌ها را انجام دهید. تنها نکته‌ای که باید توجه داشته باشید این است که سوئیفت در برخورد با اعداد و این آپریتر، آن عبارت را محاسباتی در نظر می‌گیرد و در برخورد دو یا چند رشته، آن عبارت را عمل متصل کردن و الحالق ( Concatentation ) در نظر می‌گیرد. 

تفریق ( - )

برای کم کردن دو مقدار عددی از هم استفاده می‌شود؛

var number_one, number_two : Int8
number_one = 80
number_two = 30
print("Result => ", number_one - number_two) // Output the number 50

مثال بالا به خوبی نشان می‌دهد که دو مقدار ۸۰ و ۳۰ از هم کم شده و در نتیجه، خروجی برابر ۵۰ خواهد بود.

ضرب (‌ * )

 عمل ضرب کردن دو عدد را انجام می‌دهد؛

var number_one, number_two : Int8
number_one = 50
number_two = 20
print("Result => ", number_one * number_two) // Output the number 1000

دقت کنید که  نباید به حرف ( x ) که شبیه به ضرب در ریاضیات است اشتباه گرفته شود. 

تقسیم ( / )

عمل تقسیم کردن دو عدد را انجام می‌دهد؛ 

var number_one, number_two : Double
number_one = 50.0
number_two = 20.0
print("Result => ", number_one / number_two) // Output the number 2.5

در محاسباتی که عمل تقسیم را انجام می‌دهیم باید به این نکته دقت کنیم که اگر پروژهٔ ما عملا برای محاسبات کار خاصی است باید از نوع دادهٔ Double یا Float استفاده کنیم که البته در محاسبات معمولی، نوع دادهٔ Float جواب‌گوی نیاز ما هم هست، اما در محاسباتی که نیاز به دقت بالایی دارند باید از نوع دادهٔ  Double استفاده کنیم.

باقی‌مانده ( ٪ )

توجه داشته باشید که این علامت را با درصد که شبیه همین است اشتباه نگیرید! چرا که در دنیای واقعی ما، علامت درصد برای نشان دادن مقداری از چیزی در یک محصول یا خدمات است ولی در دنیای کامپیوتر و برنامه‌نویسی این علامت، به معنای باقی ماندهٔ بین دو عدد است که بعد از تقسیم‌های پی‌درپی که صورت می‌گیرد، بدست می‌آید. این باقی مانده یا ۰ است یا ۱ ( حتما شما هم عاشق صفر و یکی هستید که اساس کار کامپیوتر و سیستم شما را تشکیل می‌دهد! ). 

این مثال را ببینید تا بهتر متوجه این موضوع شوید؛ 

var number_one, number_two : Int8
number_one = 10
number_two = 2
print("Result => ", number_one % number_two) // Output the number 0

اگر جزئی‌تر بخواهیم وارد شویم به این صورت است که ابتدا عدد ۱۰ بر ۲ تقسیم ( / ) شده و سپس حاصلی که بدست می‌آید ۵ است و سپس دوباره ۵ تقسیم بر ۲ شده و ۲ بدست می‌آید و در اینجا باقی‌مانده ۲ ٪ ۲ می‌شود ۰.

 

آپِریِتر‌های مُرکب ( Compound Assigment Operator ) 

که شامل عبارت‌های کوتاه‌شده یا به اصطلاح میانبری برای عمل انتساب و محاسبه را فراهم می‌کند که شامل: =+،=-،=*،=/،=٪ است. در زیر توضیح مختصر به همراه یک مثال آورده شده است.

انتساب و جمع ( =+ )

در این حالت ما هم عمل انتساب را داریم و هم عمل جمع، با یک تیر دو نشان بزنید! به مثال زیر دقت کنید.

var number_one : Int8 = 50
number_one += 50
print("Result =>", number_one) // Output the number 100

 در خط دوم که ما با آن کار داریم، متغییر number_one مقدار ۵۰ را هم به آن اضافه به خودش اضافه کرده و در نهایت در خود متغییر  number_one ذخیره و نتیجه ۱۰۰ نمایش داده می‌شود. که بدون استفاده از میانبر، به این شکل بود؛

var number_one : Int8 = 50
number_one = number_one + 50
print("Result =>", number_one) // Output the number 100

 حتی می‌توانیم برای اتصال یک رشته به رشتهٔ دیگر استفاده کنیم؛

var web_site_name : String = "www.iostream.ir :) "
web_site_name += " www.fanoox.com ;) "
print("Result =>" web_site_name) // Ouput the web site of name => www.iostream.ir :) www.fanoox.com ;)

که در شکل ساده به این شکل نوشته می‌شد؛

var _web_site_name_and_platform_name : String = "www.iostream.ir :) " + " www.fanoox.com ;) "
print("Result => ", _web_site_name_and_platform_name) // Ouput the web site of name and platform name => www.iostream.ir :) www.fanoox.com ;) 

انتساب و تفریق ( -‌ )

مقدار سمت راست را از مقدار سمت چپ کم می‌کند و نتیجه در همان متغییر ذخیره خواهد شد؛

var number : Int8 = 80 
number -= 30
print("Result =>", number) // Ouput the number 50

مقدار ۸۰ که مقدار فعلی متغییر number است، از مقدار ۳۰ که در سمت راست متغییر قرار دارد، کم می‌شود و در نهایت مقدار ۵۰ در همان متغییر یعنی ‌number ذخیره خواهد شد.

انتساب و ضرب ( =* )

ضرب مقدار سمت راست در مقدار فعلی متغییر سمت چپ را انجام می‌دهد؛

var number : Int8 = 80
number *= 30
print("Result =>", number) // Ouput the number 2400

انتساب و تقسیم ( / )

مشابه آپِریِتر تقسیم ( / )‌، تقسیم مقدار سمت راست را به متغییر سمت چپ انجام می‌دهد؛

var number : Int8 = 10
number /= 2
print("Result =>", number) // Ouput the number 5

انتساب و باقی‌مانده ( ٪ )

عمل باقی‌ماندهٔ دو عدد که شامل مقدار فعلی متغییر سمت چپ و مقدار سمت را است را محاسبه کرده و در متغییر سمت چپ ذخیره می‌کند؛

var number : Int8 = 10
number ٪= 5
print("Result =>", number) // Ouput the number 0

 

 آپِریِتر‌های مقایسه‌ای ( Comparison Operators ) 

برای مقایسهٔ بین دو مقدار و در نتیجه به دست آوردن مقدار True یا False مورد استفاده قرار می‌گیرند. بیشترین استفادهٔ آنها در شرط‌‌ها است، اما می‌توان به صورت مستقیم هم از آن‌‌ها هم استفاده کرد. این آپِریِتر‌ها شامل ==،=!،>،<،=<،=>،==!،=== هستند. برای هر کدام مثالی در زیر آورده شده است. 

مساوی ( == )

برای مقایسه دو مقدار استفاده می‌کنیم که در صورتی که مقادیر دو طرف مساوی باشند، مقدار True و در غیر اینصورت مقدار  False برگشت داده خواهد شد؛

print("True and False => ", 2 == 2) // Output the true 
print("True and False => ", 2 == 3) // Output the false

در مثال بالا به دلیل این‌که ۲ با ۲ برابر است،‌ مقدار  نمایش داده شده،‌ true است. و در خط بعدی به این دلیل که مقدار ۲ برابر با ۳ نیست،‌ مقدار false نمایش داده می‌شود.همچنین می‌توانید در شرط‌ها و حلقه‌ها هم استفاده کنید:

if 2 == 2 {
  print("Ok!")
}else {
   print("NO!")
}
// Ouput the string Ok!

نامساوی ( =! )

اگر مقدار برابر با مقدار مقابل خودش نباشد، نتیجه true و در غیر اینصورت نتیجه false خواهد بود. علامت ! ( نَقیض )‌ دقیقا معنا و مفهوم ( == ) را عوض می‌کند ( یعنی اگر مقداری true باشد، برعکس شده ( false ) و اگر false باشد ( true ) می‌شود. 

 

print("True and False => ", 2 != 3) // Output the true 
print("True and False => ", 2 != 2) // Output the false

در مثال بالا، ۲ مساوی ۳ نیست و این درست است!. در خط بعدی ۲ برابر با ۲ است و این درست است! که در نتیجه، برعکس آن یعنی false نمایش داده می‌شود.

کوچک‌تر (‌ > ) 

اگر مقدار سمت چپ کوچک‌تر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false است؛

print("The operator ( < ) => ", 1 < 2) // Output the boolean true 
print("The operator ( < ) => ", 2 < 1) // Output the boolean false

بزرگ‌تر ( <‌‌ )

اگر مقدار سمت چپ بزرگ‌تر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false خواهد بود؛

print("The operator ( > ) => ", 1 > 2) // Output the boolean false
print("The operator ( > ) => ", 2 > 1) // Output the boolean true

بزرگ‌تر یا مساوی ( =< )

اگر مقدار سمت چپ، بزرگتر یا مساوی مقدار سمت راست بود، نتیجه true  است، در غیر اینصورت، نتیجه false خواهد بود؛

print("The operator ( >= ) => ", 1 >= 1) // Output the boolean true 
print("The operator ( >= ) => ", 1 >= 2) // Output the boolean false

کوچک‌تر یا مساوی ( => ) 

اگر مقدار سمت چپ، کوچکتر یا مساوی مقدار سمت راست بود، نتیجه true  است، در غیر اینصورت، نتیجه false است؛ 

print("The operator ( <= ) => ", 1 <= 2) // Output the boolean false
print("The operator ( <= ) => ", 1 <= 1) // Output the boolean true

نکته:‌ اولویت مساوی (‌ = ) در این مورد بالا‌تر از بزرگ‌تر < یا کوچک‌تر > است و بنابر‌این در حلقه‌ها اگر این آپِریِتر باشد، اولویت با آن است.

 

مقایسهٔ دو شئ ( === ) 

 برای مقایسهٔ دو شئ ( object ) استفاده می‌شود. اگر هر دو شئ از یک مرجع ( refrence ) باشند یا به عبارت دیگر شئ‌های ساخته شده در حافظهٔ به نام Heap با تمام ویژگی‌ها و متغییر‌‌ها نگه‌داری شوند و اگر شئ دیگر از همان حافظه‌ای که یک شئ دیگر استفاده می‌کند وجود داشته باشد، این آپِریِتر درمورد آن دو شئ نتیجهٔ true و در غیر اینصورت نتیجهٔ false را نمایش می‌دهد. در مبحث شئ‌گرایی بیشتر در این مورد صحبت خواهیم ‌کرد،‌ در حال حاضر فقط همین را که بدانید، کافیست. به مثال زیر دقت کنید:

class WebsitePlatform {
  var website_name, platform_name : String
  init(web_name : String, platform : String) {
    self.website_name = web_name
    self.platform_name = platform
  }
}
let _web_site_and_platform_one = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com")
let _web_site_and_platform_two = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com")
if _website_and_platform_one === _website_and_platform_two {
   print("This is refrence!")
}else {
   print("No,this is not refrence!")
}

اگر این قطعه کد را اجرا  کنید، به شما پیغام NO, this is not refrence را می‌دهد! چرا که هر دو شئ به صورت جداگانه در حافظهٔ Heap ذخیره شده‌اند و هیچ‌کدام به دیگر ارجاعی ندارد و به اصطلاح با هم ارتباطی ندارند و اگر ما بیایم به این شکل عمل کنیم، آنوقت دیگر یک ارجاع داریم به یک شئ‌ مشخص؛

class WebsiteAndPlatform {
  var website_name, platform_name : String
  init(web_name : String, platform : String) {
    self.website_name = web_name
    self.platform_name = platform
  }
}
let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com")
let _website_and_platform_two = _website_and_platform_one
if _website_and_platform_one === _website_and_platform_two {
   print("This is refrence!")
}else {
   print("No,this is not refrence!")
}

به جای ایجاد شئ جدید، همان شئ اول را به متغییر دوم انتساب می‌دهیم که در واقع الان دو شئ داریم که شئ دومی به شئ اولی اشاره می‌کند. یعنی اینکه الان با هم در ارتباط هستند و شئ دومی ارجاعیست به شئ اول؛ نتیجه خروجی هم This is refrence است.

نامساوی بودن دو شئ ( ==! )

اگر دو شئ از یک مرجع نبودند، و هر کدام در حافظه‌ای جداگانه نگه‌داری می‌شوند، نتیجه به صورت true و اگر دو شئ‌ از یک مرجع بودند، نتیجه false خواهد بود. کاملا برعکس علامت (‌ ===‌ ). به مثال زیر دقت کنید:

class WebsiteAndPlatform {
  var website_name, platform_name : String
  init(web_name : String, platform : String) {
    self.website_name = web_name
    self.platform_name = platform
  }
}
let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com")
let _website_and_platform_two = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com")
if _website_and_platform_one !== _website_and_platform_two {
   print("This is refrence!")
}else {
   print("No,this is not refrence!")
}

مثال بالا هم که کاملا واضح است! اینکه اگر دو شئ با هم ارجاعی نداشتند، پس نتیجه true است و در غیر اینصورت اگر ارجاع داشتند، نتیجه false و شرط آخر اجرا خواهد شد که No, this is not refrence  است. 

آپریتر ترِنِری ( Ternary Conditonal Operators )

سه  قسمت دارد؛
  1. مسئله/شرط
  2. مقدار اول
  3. مقدار دوم

ابتدا شرط قرار خواهد گرفت و سپس به دنبال آن آپِریِتر ? و بعد از آن جواب اول که  در صورت درست بودن شرط، برگشت داده می‌شود و علامت کالُن ( : ) بعد از جواب اول قرار می‌گیرد که در صورتی که نتیجه نادرست یا false باشد، مقدار بعد ( : ) برگشت داده می‌شود. به مثال زیر توجه کنید؛

let _website_name_and_platform_name : String = 2 > 1? "www.iostream.ir" : "www.fanoox.com"
print("Result =>", _website_name_and_platform_name) // Output the www.iostream.ir

در مثال بالا همان‌طور که مشاهده می‌کنید، ابتدا شرط یا مسئله قرار می‌گیرد و سپس مقدار بعد آپِریِتر ? و مقدار اول و دوم که با ( : ) از هم جدا می‌شوند. در این مثال نتیجه،  www.iostream.ir است، چرا که ۲ بزرگتر از ۱ است و این کاملا منطقی است که نتیجهٔ true دارد. 

آپریتر دامِنه ( Range Operator ) 

بیشتر در حلقه‌ها استفاده می‌شود و نحوهٔ کار آن‌ را در جلسهٔ قبل توضیح داده‌ شده است؛

for index_number_one in 0...20 {
 print(index_number_one, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
}
for index_number_two in 0..<20 {
   print(index_number_two, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19
}

 

آپریتر‌های منطقی ( Logical Operators )

شامل !،&&،|| هستند که بیشتر استفادهٔ آن‌ها در حلقه‌هاست، اما شما می‌توانید در هر جایی از پروژهٔ خودتان که نیاز به آن‌ها داشتید، استفاده کنید.

نَقیض ( ! ) 

کار آن، برعکس کردن یا نقض کردن یک مقدار است که امکان دارد true یا false باشد. به عنوان مثال اگه مقدار متغییری true است و این آپِریِتر را در ابتدای آن مقدار قرار بدهید، خروجی برابر است با false. و همین مورد هم برعکس صدق می‌کند، یعنی اگر شما مقدار متغییری false داشتید، با گذاشتن این عبارت در ابتدای متغییر، نتیجه true خواهد شد؛ 

var isname_website_iostream : Bool = false 
print(!is_name_website_iostream) // Output the bool true 
isname_website_iostream = true 
print(!isname_website_iostream) // Output the bool false

درست بودن دو یا چند شرط ( && )

اگر در شرط یا عبارتی بخواهیم دو شرط را بررسی کنیم که هر دو هم حتما باید درست ( true ) باشند از این آپِریِتر استفاده خواهیم کرد؛ 

let web_sitename, platform_name : String 
web_sitename = "www.iostream.ir" 
platform_name = "www.fanoox.com"
if web_sitename == "www.iostream.ir" && platform_name == "www.fanoox.com" {
  print(web_sitename, platform_name)
} else {
   print("None")
}

در قطعه کد بالا، هر دو شرط مبنی بر اینکه دو مقدار متغییر تعریف شده باید برابر با مقدار تعیین شده در شرط باشند تا مقادیر چاپ شوند. در غیر اینصورت با خروجی None روبرور خواهیم شد. 

درست بودن حداقل یک شرط ( || ) 

اگر یکی از شرط‌ها در بین چندین شرط که برقرار است و به عبارتی نتیجه درست (‌ true ) داشته باشد، وارد بدنهٔ شرطه خواهد شد و دستورات را اجرا می‌کند. اگه تمامی شرط‌ها نادرست (‌ false ) باشند، دستورات داخل بدنه اجرا نخواهند شد؛

var web_sitename, platform_name : String 
web_sitename = "www.iostream.ir" 
platform_name = "www.fanoox.com"
if web_sitename == "www.iostream.ir" || platform_name == "www.fanoox.ir" {
  print(web_sitename, platform_name)
} else {
   print("None")
}

در مثال بالا شرط دوم برقرار نیست! چرا که متغییر platform_name با مقدار سمت راست آن برابر نیست. اما از آنجایی که از ( ||‌ ) استفاده کرده‌ایم، پس شرط اول درست بوده و دستورات داخل بدنهٔ شرط if اجرا خواهند شد. 

کلمات کلیدی continue,break,fallthrough

کلمهٔ کلید continue 
اگر بخواهیم در یک حلقه در یک جایی به بعد دستورات اجرا نشوند و حلقه مقدار فعلی را نادیده بگیرد، از این کلمهٔ کلید کمک خواهیم گرفت؛
for index in 0...20 {
  if index == 5 {
        continue
    }
  print(index)
}
/* Output the number 
0
1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
*/

همان‌طور که در مثال بالا مشاهده‌ می‌کنید، در حلقهٔ for شرط داخل حلقه بر این مبنا است که هر زمانی که متغییر index مساوی مقدار ۵ شد، به ادامهٔ دستورات پایان بده ( continue ) و مجدد حلقه را از سر بگیر. به همین خاطر است که عدد ۵ نمایش داده نشده است.

کلمهٔ کلید break 

با این کلمهٔ کلید به راحتی می‌توانید هر جایی از حلقه که دیگر نیازی نداشتید ادامه پیدا کنید، حلقه را متوقف یا به اصطلاح بشکنید!. با این کار دیگر حلقه تکرار نشده و دستورات بعد از حلقه اجرا خواهند شد؛

for index in 0...5 {
   if index == 2 {
      break
   }
   print(index)
}
/* Output the number 
0
1 
*/

کلمهٔ کلید fallthrough 

شاید در جایی از دستور شرطی switch لازم داشتید که caseهای بعدی هم اجرا شوند. با این کلمهٔ کلیدی می‌توانید این کار را انجام دهید؛

let _number : Int8 = 1
switch _number {
   case 2:
     print(2)
   case 1: 
     print(1)
    fallthrough 
   case 3: 
     print(3)
    fallthrough
    default:
      print("None")
}

بعد از هر caseی که می‌خواهید اجرا شود باید این کلمهٔ کلیدی را قرار دهید. 

 

امیدوایم این جلسه هم مورد رضایت شما عزیزان قرار گرفته باشد.

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه پنجم

مواردی که در این جلسه یاد خواهید گرفت: متغییر آپشِنال (‌Optionals Variable ) ، رشته‌ها و کارکتر‌ها (‌String & Character‌ )

 

متغییر‌های آپشِنال ( Optionals Variable‌ ) چیستند؟‌

این نوع متغییر‌ها، برای مدیریت دادهٔ شما استفاده می‌شوند! همان‌طور که از نام آن‌ها هم مشخص است، به معنی اختیاری! یعنی یا یک مقدار وجود دارد یا ندارد! در سوئیفت، شما باید بعد از تعریف یک متغییر‌ مقدار آن را هم تعیین کنید و نمی‌توانید آن را بدون مقدار به حال خود رها کنید! به عنوان مثال کُد زیر را ببینید:

var website_name 

print(website_name) // Error compiler

در صورتی که این کد را اجرا کنید، با خطای کامپایلر مواجه می‌شوید. دلیلش هم آن است که در این زبان،‌ باید مقدار هر متغییر را باید بلافاصله بعد از تعریف آن بدهید و  حالت پیش‌فرض نخواهیم داشت (‌ در برخی از زبان‌ها حالت پیش‌فرضی برای متغییر‌ها در نظر گرفته می‌شود مانند ++C ) این موضوع با نوع هم بخواهید تعریف کنید باز هم به خطای کامپایلر خواهید خورد: 

var website_name : String

print(website_name) // Error compiler

اما اگر به آن مقدار خالی ( "" => دابل کوتیشن )‌  بدهید، خروجی را برای شما نمایش خواهد داد، اما فقط خالی!:

var website_name : String = ""

print(website_name) // Print empty

این برای همهٔ نوع‌های دادهٔ دیگر هم صدق می‌کند. اما هر دفعه در کدهای خودتان برای بررسی کردن آن‌ها باید شرط بگذارید ( if,else,ifelse و .. ) که ببینید کداممتغییر مقدار دارد یا ندارد. از این گذشته، با اینکار کد‌های تمیزی هم نخواهید داشت. پس این‌جا باید از آپشنال‌ها استفاده کنیم. به این قطعه کد دقت کنید:

var website_name  : String? // website_name is automatically set to nil

if name == nil{
  print("website_name has nil value")
}

در مثال بالا، شما تعریف متغییر آپشنال ( Optional ) را می‌بینید که با علامت سوال ( ? ) همراه است. ابتدا شما باید، کلمهٔ کلیدی var را همراه با یک اسم، بیاورید و بعد با استفاده از دو نقطه ( : ) که کالُن در برنامه‌نویسی خوانده می‌شود استفاده کنید. و درنهایت به همراه نوع داده و علامت سوال را در جهت انگلیسی ( ? )‌  قرار می‌دهید. متغییر شما در حال حاضر مقدار nil را دارد که به صورت اُتوماتیک، به متغییر شما داده شده است که خود شما هم می‌توانید این مقدار را برای تمای متغییرهای آپشنال خودتان قرار دهید. nil به معنای هیچ یا هیچ‌چیز است. یعنی الان هیچ داده‌ای ندارید. حالا شما می‌توانید هر زمانی که خواستید، به متغییر خود مقدار بدهید.

نکته

 متغییر آپشنال شما به اصطلاح ( Wrapper )‌ به معنی بسته‌بندی، روپوش شده است! یعنی این‌که داده‌های متغییر شما بسته‌بندی شده و در هنگامی که نیاز به اطلاعات آن داشتید باید با استفاده از علامت تعجب (‌ ! ) آن را  ( Unwrapper ) کنید و یا از حالت بسته‌بندی شده خارج و اطلاعات خودتان را دریافت کنید! به عبارتی دیگر، اطلاعاتی که شما در متغییر خودتان ذخیره کردید در حالت آپشنال، بین دو پرانتز قرار گرفتند و به همین خاطر به آن می‌گویند Wrapper یا محافظت‌ شده است!. به این مثال دقت کنید:

var website_name  : String? = "www.iostream.ir"
if name == nil{
  print("website_name has nil value")
}
else{
  print(website_name!) // Print www.iostream.ir
}

همان‌طور که در مثال بالا مشاهده می‌کنید، اگه متغییر ما مقداری نداشت ( nil )، شرط اول اجرا خواهد شد و در غیر اینصورت، مقدار www.iostream.ir نمایش داده می‌شود. شما می‌توانید در هر زمانی که نیاز داشتید، متغییر خودتان را برابر با nil کنید:

var website_name  : String? = "www.iostream.ir"
website_name = nil
if name == nil{
  print("website_name has nil value")
}
else{
  print(website_name!) // Print www.iostream.ir
}

خروجی برابر است با؛ website_name  has nil value. به خاطر داشته باشید که به هیج وجه نمی‌توانید به متغییر‌های عادی  کلمهٔ کلیدی nil رو بدهید! این فقط برای متغییر‌های آپشنال است.

رِشته‌ها و کارِکتر‌ِها (‌String & Character‌ )

رشته‌ها مجموعه‌ای از کارکترها هستند که یک حرف یا یک متن کامل را درون خودشان ذخیره می‌کنند ( همان متن یا نوشته‌ ). مانند  "www.iostream.ir" و یا "Apple". و کارکترهایی که در نهایت می‌توانند تا دو حرف را  در خودشان ذخیره کنند،‌ مثل؛ "AP" و یا "IO". بگذارید چند نمونه بیاوریم تا بهتر و  شفاف‌تر متوجه بشوید:

let website_name : String = "www.iostream.ir"
print(website_name)

و یا این‌که یک کارکتر داشته باشیم؛ 

let company_name : Character = "A" 

print(company_name) 

دقت داشته باشید که در حال حاضر که این زبان در این نسخهٔ یعنی ( 5.1 ) به سر می‌برد، تنها از یک کارکتر پشتیبانی می‌کند اما در مورد کارکتر‌های یونیکُد ( Unicode ) این‌گونه رفتار نمی‌کند و هیچ اخطاری از سمت کامپایلر، داده نمی‌شود. به این مثال دقت کنید؛ 

let unicode_character : Character = "\u{1F1EE}\u{1F1F7}"

print(unicode_character) // Ouput iran flag 

در خروجی می‌توانید مشاهده کنید که پرچم کشورمان نمایش داده می‌شود و آن هم به دلیل استفاده از کارکتر‌های یونیکد است. بنابراین،  در این مورد بدون اینکه نوع دادهٔ کارکتر (‌ Character ) به کارکتر‌های یونیکد، ایرادی بگیرد، معادل آن را که حاوی یک کارکتر است ( در این مثال پرچم ایران که خود یک کارکتر است ) ذخیره می‌کند. اما درمواردی دیگر به علت اینکه که کارکتر یونیکدی نخواهیم داشت، بیش‌تر از یک کارکتر بخواهیم ذخیره کنیم باید از نوع دادهٔ رشته ( String ) استفاده کنیم نه Character.

تعریف رشته

شما با تعریف یک متغییر یا ثابت، نام آن و در نهایت نوع و مقدار آن، می‌توانید یک رشته یا همان دنباله‌ای از کارکتر‌ها داشته باشید. و یا از سازنده (‌در محبث کلاس‌ها کامل دربارهٔ آن توضیح خواهیم داد) خود نوع String استفاده کنید؛

let website_name : String = String("www.iostream.ir")
print(website_name)

یا این‌که به صورت کوتاه شده،‌ بدون تعریف صَریح نوع، آن را به این شکل بنویسید:

let website_name = "www.iostream.ir"
let platform_name = String("www.fanoox.com")
print("Website name : \(website_name) and Platfrom name : \(platform_name)")

خالی قرار دادن رشته

ما می‌توانیم به دو صورت به متغییرها رشته‌‌ای خود مقدار خالی بدهیم! یا با استفاده از دو دابِل کُوتِیشِن ( "" )‌ یا با استفاده از یک نمونه از نوع رشته ( ()String ). به مثال‌های زیر دقت کنید:

let website_name = ""
let platform_name = String()
print(website_name,platform_name) // Empty

بررسی خالی بودن یا نبون رشته

شما می‌توانید با استفاده از ویژگی isEmpty از کلاس String، بررسی کنید که آیا متغییر شما خالی است یا نه؟ به مثال زیر دقت کنید:

let website_name = ""
if website_name.isEmpty { // True 
  print("website_name is empty!")
}

متصل کردن دو رشته 

با استفاده از آپِریِتر + شما می‌توانید دو یا چند رشته را به هم متصل کنید؛

let website_name : String = "www.iostream.ir"
let platform_name : String = "www.fanoox.com"
let addition : String = website_name + " and " + platform_name
print(addition) // www.iostream.ir and www.fanoox.com

یا این‌که از حالت کوتاه‌ شدهٔ آن استفاده کنید؛

let website_name : String = "www.iostream.ir"
let platform_name : String = "www.fanoox.com"
website_name += " and " + platform_name
print(addition) // www.iostream.ir and www.fanoox.com

ترکیب اطلاعات با یک رشته

همچنین شما می‌توانید یک رشتهٔ حاوی اطلاعات داشته باشید و در عین حال آن‌ها در خروجی برای ذخیره در متغییر‌های دیگر استفاده کنید! چگونه؟ به این صورت؛ 

let website_name : String = "www.iostream.ir"
let platform_name : String = "www.fanoox.com"
let addition = "Website name : \(website_name) and Platfrom name \(platform_name)"
print(addition) // Website name www.iostream.ir and Platform name www.fanoox.com

با استفاده از این الگو ()\ شما می‎توانید تا بی‌نهایت اطلاعات در داخل یک رشته قرار بدهید! فقط کافی است متغییرها، ویژگی‌های یک کلاس،‌ توابعی که مقدار برگشتی دارند ( درمورد توابع در جلسات بعد کاملا صحبت خواهیم کرد ) و هر چیزی که حاوی داده یا همان اطلاعات باشد قرار بدهید. اول یک اِسلش رو به عقب (‌ Backward Slash ) و بعد از آن هر اطلاعاتی که می‌خواهید داخل رشته باشند را داخل دو پرانتز () قرار می‌دهید.

بدست آوردن طول یک رشته

برای به دست آوردن طول یک رشته از ویژگی count‌ از کلاس String استفاده می‌کنیم؛

let website_name : Stirng = "www.iostream.ir"
print(website_naem.count) // website_name length is 15

اگر تک‎تک کارکترهای www.iostream.ir را بشمارید، می‌بینید که مقدار 15 به دست می‌آید. پس در خروجی هم عدد 15 را خواهیم داشت. 

مقایسه دو رشته

اگه بخواهید یک رشته را با یک رشتهٔ دیگه مقایسه کنید، می‌توانیم بطور مستقیم یا با استفاده از شرط‌ها این کار را انجام دهیم؛

let website_name : String = "www.iostream.ir"
let platform_name : String = "www.fanoox.com"
print(website_name == platform_name) // False
if website_name == platfrom_name { // False
  print("Equal")
}
else {
  print("Not Equal") // Not Equal 
}

با آپِریِتر == در شرط if بررسی می‌کنیم که آیا website_name و platform_name با هم مساوی هستند یا نه، که Not Equal یعنی برابر نیستند را در خروجی خواهیم داشت.

بررسی شروع یا پایان یک رشته 

با دو متد ( در جلسات آینده با متد‌ها  کاملا آشنا خواهید شد )  hasPrefix و hasSuffix‌ می‌توانیم بررسی کنیم که آیا رشتهٔ ما با ورودی که می‌دهیم، مطابقت دارد یا نه. به عنوان مثال رشتهٔ www.iostrea.ir رو می‌خواهیم بررسی کنیم که با www شروع می‌شود یا نه. برای این کار از متد hasSuffix استفاده می‌کنیم:

let website_name : String = "www.iostream.ir"
print(website_name.hasSuffix("wwww")) // False
// Or
if website_name.hasSuffix("www") { // True
 print(website_name) // www.iostream.ir
}

خروجی اول False است! چرا که ورودی ما (‌ wwww ) است و با اول رشتهٔ www.iostream.ir مطابقت ندارد ولی در دستور شرطی ( if )  که گذاشتیم، مقدار True  است. چرا که ورودی ما ( www ) با اول www.iostream.ir مطابقت دارد. 

حالا اَگه بخواهیم که آخر رشتهٔ خود را بررسی کنیم که آیا آن چیزی که می‌خواهیم، با آخر رشته تمام می‌شود یا نه، از متد hasPrefix استفاده می‌کنیم:

let website_name : String = "www.iostream.ir"
print(website_name.hasPrefix(".com")) // False
// Or
if website_name.hasPrefix(".ir") { // True
 print(website_name) // www.iostream.ir
}

خروجی False و www.iostream.ir است. آخر دامنه وب‌سایت www.iostream.ir با ( ir. ) تمام می‌شود اما ما دامنهٔ com.  را قرار دادیم که در نتیجه False‌ خواهد شد. ولی در دستور شرطی یعنی if این موضوع درست است! چرا که دامنهٔ وب‌سایت با ir. تمام خواهد شد و این متد هم همین را می‌خواهد! پس در نتیجه True و مقدار متغییر website_name نمایش داده می‌شود. 

 

امیدواریم که این جلسه مورد رضایت شما عزیزان قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه ششم

مواردی که در این جلسه یاد خواهید گرفت: آرایه‌ها (‌ Arrays )

آرایه‌‌ها چیستند؟ 

اگر شما یک بسته کِبریت را تصور کنید، حداقل تا 50 تا دانه کبریت داخل آن است! همهٔ آن‌ها هم همه کبریت هستند نه چیز دیگر. البته می‌شود چیز دیگری هم گذاشت داخل آن اما در برنامه‌‌نویسی نمی‌توانید همچین کَلکی را سوار کنید! ( در بعضی از زبان‌های برنامه‌نویسی ). آرایه‌ها در سوئیفت مجموعه‌ای از مقادیر را داخل خودشان نگه‌داری می‌کنند و مانند یک متغییر می‌مانند با این تفاوت که یک متغییر معمولی یک مقدار رو می‌تواند ذخیره کند ولی متغییر آرایه‌ای این‌گونه نیست. به این دنبالهٔ عددی دقت کنید؛

1,2,3,4,5,6,7,8,9,10

به‌نظر شما می‌شود این‌ها را در یک متغییر معمولی ذخیره کرد؟‌ به طوری که هر کدام از عدد‌ها را که بخواهیم سریع به ما بدهد؟ مسلما خیر. تازه اگر شما بخواهید برای هر کدوم از این اعداد، یه متغییر جداگانه تعریف کنید؛استاندارد پروژه‌‌تان به شدن پایین می‌آید و زبانی هم که با آن برنامه‌نویسی می‌کنید به همان مقدار به شما واکنش نشان خواهد داد ( هر کُنشی واکنشی دارد...!? ) کاهش سرعت اجرا، زیاد‌نویسی، اگه برای سایر توسعه‌دهنده‌های دیگر باشد، به احتمال زیاد طرف پروژهٔ شما نمی‌آیند! به عنوان مثال، تعریف متغییر بدون آرایه؛ 

let number_one : Int8 = 1
let number_two : Int8 = 2
let number_three : Int8 = 3
let number_four : Int8 = 4
let number_five : Int8 = 5
let number_six : Int8 = 6
let number_seven : Int8 = 7
let number_eight : Int8 = 8
let number_nine : Int8 = 9
let number_ten : Int8 = 10

خودتان باشید، حاضرید به این شکل پروژه‌‌ای را به این شکل پیش ببرید؟! حالا فکر کنید ۱۰۰۰ دادهٔ مختلف بخواهید تعریف کنید! تعجب می‌کنید، اینطور نیست؟! اما خوشبختانه همیشه راه نجات هست... آن هم استفاده از آرایه‌ها است! آرایه‌ها به شما کمک می‌کنند تا داده‌های زیادی که مورد نیاز پروژهٔ شما باشد، تعریف و  استفاده کنید.

نحوهٔ تعریف 

به سه روش می‌توانید آرایه‌های خودتان را تعریف کنید؛
  • استفاده از نوع و سازنده ( Construct )
  • استفاده از کلاس Array، نوع متغییر و سازنده 
  • تعریف آرایه بدون هیچ واسطه‌ای!

نکته

آرایه‌های سوئیفت از موقعیت ( Index ) صفر (‌ ۰ ) شروع خواهند شد. در ادامه متوجه این موضوع خواهید شد، اما همیشه این را به خاطر داشته باشید که اولین عضو در یک آرایه در موقعیت صفرم آن آرایه قرار می‌گیرد و به همین ترتیب، موقعیت اول، حاکی از مقدار دوم، موقعیت دوم، مقدار سوم و الی آخر... پس این مورد را در پروژه‌هایتان حواستان باشد! چرا که با یک اشتباه، ساعت‌ها زمان و انرژی خود را تَلف می‌کنید تا یک اشتباه کوچک را پیدا و رفع کنید.

 

اولین مورد که در لیست بالا گفته شده،‌ به این صورت است که شما یک متغییر تعریف می‌کنید ( از کلمات کلیدی var و یا let می‌توانید استفاده کنید) و بعد یک نام شفاف و دلخواه خواهید نوشت و در نهایت از نوع و سازنده به این شکل استفاده می‌کنید؛

var first_array = [Int]()
print(first_array) // Output is empty or []

در روش دوم می‌توانید از کلاس Array‌ استفاده کنید! به این شکل که مشاهده می‌کنید؛

var first_array = Array<Int>()
print(first_array) // Output is empty or []

و در نهایت می‌توانیم بدون هیچ واسطه‌ای ( بدون استفاده روش اول و دوم )، آرایه‌مان را تعریف کنیم؛

var first_array = [1,2,3,4,5,6,7,8,9,10]
print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10]

به نظر می‌آید که این برای شما راحت‌تر و قابل‌درک‌تر باشد تا موارد قبل،‌ اینطور نیست؟ اما خُب، آن‌ها را هم برای دوستانی که عاشق پیچدگی هستن نوشتیم! شما می‌توانید از هر روشی که مد‌نظرتان بود استفاده کنید‌. نوع داده‌ای هم که مشخص می‌کنید، بستگی به پروژهٔ شما دارد؛ 

var first_array = ["www.iostream.ir","www.fanoox.ir","www.ModernCpp.ir"]
print(first_array) // Output is empty or ["www.iostream.ir", "www.fanoox.ir", "www.ModernCpp.ir"]

همین‌طور شما می‌توانید از مقادیری پیش‌فرض برای آرایه‌هایتان ستفاده کنید! به عنوان مثال شما در همان موقعی که تعریف آرایهٔ خودتان را انجام می‌دهید، می‌خواهید تا ۱۰ خانه از آرایه‌تان داده‌های تکراری داشته باشد. این‌کار را می‌توانید با استفاده از سازنده‌ (‌ Construct ) انجام بدهید؛

var first_array = [Int](repeating: 20, count: 10)
print(first_array) // Output is [20,20,20,20,20,20,20,20,20,20]

در کد بالا گفته شدهکه عدد ۲۰ را ( repeating: 20 ) به تعداد ۱۰ بار ( count: 10 ) در آرایهٔ first_array قرار گیرد. خروجی را همان‌طور که مشاهده می‌کنید، مقدار ۲۰ به تعداد ۱۰ بار در first_array تکرار شده.

ترکیب دو آرایه با هم 

برای این‌کار  فقط کافی است با استفاده از آپِریتر +، یک آرایهٔ جدید بدست بیاوریم؛

var first_array = [1,2,3,4,5]
var two_array = [6,7,8,9,10]
var result_array = first_array + two_array
print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10]

دسترسی به کُل یا یک از  داده‌های آرایه

برای این‌که بتوانید به کل آرایه دسترسی داشته باشید و آن رو نمایش بدهید، می‌توانید به این صورت عمل کنید؛

var first_array = [1,2,3,4,5]
print(first_array) // Ouput is [1,2,3,4,5]

البته می‌توانید در مواقعی که  نیاز به آرایه کامل دارید استفاده کنید! به عنوان مثال پارامتر توابع و ... برای این‌که بتوانید به یک دادهٔ خاص که مورد‌نظر شما  است، دسترسی داشته باشید؛ باید از موقعیت ( Index ) آرایه استفاده کنید؛

var website_name = ["www.iostream.ir","www.fanoox.com","www.ModernCpp"]
var langauge_name = ["C++","C","Swift"]
print(website_name[0]) // Output is www.iostream.ir
print(langauge_name[2]) // Ouput is Swift 

در قطعه کد بالا، ابتدا باید نام  آرایه بیاورید و بعد از آن  با استفاده از دو براکت ( [] ) و قرار دادن شماره موقعیت، به مقدار آن دسترسی داشته باشید. همان‌طور هم که مشاهده می‌کنید، گفتیم که آرایه‌ها از موقعیت صفرم شروع می‌شوند که در بالا با آوردن website_name و سپس شماره موقعیت ( Index Number ) به اولین عضو آن یعنی www.iostream.ir دسترسی پیدا کرده و آن را نمایش می‌دهیم. اگر از ۲ برای آرایه استفاده کنید، به شما خروجی Swift‌ را خواهد داد! چرا که عضو دوم آرایهٔ langauge_name مقدار Swift است. 

اضافه کردن داده به آرایه

اگه بخواهیم یک عضو (‌ مقدار جدید ) به آرایه اضافه کنیم، از متُد append که مربوط به کلاس آرایه‌ها است، استفاده می‌کنیم. در جلسه‌های بعد با کلاس‌ها، و متد‌ها آشنا خواهید شد. به این مثال توجه کنید؛

var first_array = [1,2,3,4,5]
// ‌Before
print("Before \(first_array)") // Ouput is [1,2,3,4,5]

first_array.append(6)

// After

print("After \(first_array)") // Output is [1,2,3,4,5,6]

با استفاده از موقعیت ( Index ) می‌توانیم یک مقدار را به یک موقعیت یا همان خانه‌ای از آرایه که مشخص کردیم، اضافه کنیم؛ 

var first_array = [1,2,3,4,5]
first_array[0] = [10]
print(first_array) // Output is [10,2,3,4,5]

یا می‌توانیم از آپِریتر ترکیبی =+ استفاده کنیم برای اضافه کردن گروهی از داده‌ها؛

var first_array = [1,2,3,4,5]
// ‌Before 
print(first_array) // Ouput is [1,2,3,4,5]

first_array += [6,7,8,9,10]

// After 

print(first_array) // Output is [1,2,3,4,5,6,7,8,9,10]

با استفاده از متد insert می‌توانید یک عضو جدید را به موقعیتی ( Index‌ ) که مد‌نظرتان است، اضافه کنید! به عنوان مثال در آرایهٔ زیر، می‌خواهید که عدد ۳، در خانه‌ یا موقعیت آخر قرار بگیرد؛

var first_array = [1,2,3,4,5]
// ‌Before
print("Before \(first_array)") // Ouput is [1,2,3,4,5]

first_array.insert(6, at: 4)

// After

print("After \(first_array)") // Output is [1,2,3,4,5,6]

این متد دو پارامتر دریافت می‌کند؛ یکی برای عضو جدید و یکی دیگر برای موقعیتی که می‌خواهید عضو جدید قرار بگیرد که همان‌طور که مشاهده می‌کنید، مقدار ۶ در موقعیت آخر قرار گرفته است که مقدار ۵ را دارد. 

حذف یک عضو

برای حذف یک مقدار از آرایه، از متد‌های remove و removeLast استفاده می‌کنیم. اولین متد‌؛ یک موقعیت مشخص برای حذف عضو می‌خواهد، در حالی که متد دوم؛ آخرین عضو را حذف می‌کند؛

var first_array = [1,2,3,4,5]
// ‌Before remove 
print("Before \(first_array)") // Ouput is [1,2,3,4,5]

first_array.remove(at: 0)

// After remove 

print("After \(first_array)") // Output is [2,3,4,5]

// Using removeLast

first_array.removeLast() 


print(first_array) // Output is [2,3,4]

با استفاده از at: 0 در متد remove مشخص کردیم که می‌خواهیم عضو اول را حذف کنیم که در خروجی هم می‌توانید ببینید و در متد removeLast آخرین عضو آرایه ( در این مثال 5 ) رو حذف کردیم. 

و در نهایت شما می‌توانید در یک رِنج ( بازه‌ )‌ مشخص؛ که تعیین می‌کنید، عضو اضافه کنید! چیزی شبیه به حلقهٔ for! این مثال را ببینید؛

var first_array = [1,2,3,4,5]
first_array[0...4] = [6,7,8,9,10]
print("Before \(first_array)") // Ouput is [6,7,8,9,10]

گردش در آرایه 

گردش یعنی این‌که بتوانیم بین اعضای یک آرایه که یکی یکی آن‌ها را انتخاب می‌کنیم، کارهایی را که مد‌نظرمان است را انجام دهیم! که با استفاده از یک حلقهٔ for می‌توانیم در عضو‌های آن این کار را انجام دهیم. به این مثال توجه کنید؛

var first_array = [1,2,3,4,5]
for item in first_array {
print("Item :  \(item)")
}
/* Item : 1
   Item : 2
   Item : 3
   Item : 4
   Item : 5
*/

اگه بخواهیم که هم موقعیت ( Index ) و هم مقدار آرایه رو داشته باشیم؛ از متد enumerated استفاده می‌کنیم که به ما یک تاپِل ( Tuple ) خواهد داد ( در جلسات بعد بعدا مفصلا دربارهٔ تاپل‌ صحبت خواهیم کرد) و در حلقه استفاده می‌کنیم؛

var first_array = [1,2,3,4,5]
for (index,item) in first_array.enumerated() {
print("Index of :  \(index) and Item : \(item)")
}
/* Index of : 0 and Item : 1
   Index of : 1 and Item : 2
   Index of : 2 and Item : 3
   Index of : 3 and Item : 4
   Index of : 4 and Item : 5
*/

Count و isEmpty ( دو ویژگی از کلاس آرایه )‌ 

شاید بخواهید بدانید تعداد عضو‌های یک آرایه به چه تعدا هستند؟ این مورد به خصوص در حلقه‌ها و یا موقعیت‌های دیگر بسیار موثر خواهد بود! برای این‌کار از ویژگی (‌ Property ) به نام count استفاده می‌کنیم که فقط خواندنی ( read-only ) است و هیچ مقداری رو نمی‌توانید به آن ضافه کنید! (‌ درمورد ویژگی‌ها مفصلا در جلسات  بعد توضیح خواهیم داد ) و فقط می‌توانید از مقدار آن که تعداد اعضای آرایه است، استفاده کنید؛

var first_array = [1,2,3,4,5]
print(first_array.count) // Output is 5

اگه هم می‌خواهید خالی بودن یا نبودن یک آرایه را  بررسی کنید؛ متد isEmpty‌  این امکان را در اختیار شما قرار داده است؛

var first_array = [1,2,3,4,5]
if first_array.isEmpty {
 print("Empty")
} else {
 print("Not Empty") 
}
// Not Empty 

امیدواریم که این جلسه مورد رضایت شما عزیزان باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه هفتم

مواردی که در این جلسه یاد خواهید گرفت: مجموعه‌ها ( Collections ) 

مجموعه‌ها در سوئیفت در واقع متغییر‌هایی هستند که بیش‌از یک مقدار را نگهداری می‌کنند و هر کدام، هم طبق عملکردی که دارد، داده‌ها را ذخیره و در اختیار برنامه‌نویس می‌گذارد. منظور از هر کدام، ۴ نوع مجموعه است که در اینجا مشاهده خواهید کرد؛ 

  • آرایه‌ ( Array )
  • سِت‌ ( Set )
  • دیکشنری ( Dictionary )
  • تاپِل‌ ( Tuple )‌ 

در جلسهٔ قبل، با اولین مجموعه؛ یعنی آرایه‌ها به طور کامل آشنا شدید و در این جلسه با سِت‌ها (‌ Sets )‌ کامل آشنا خواهید شد. به خاطر داشته باشید که  هر کدام از این مجموعه‌ها منحصر‌ به فرد عمل کرده و هیچ‌کدام شبیه هم نخواهند بود. 

سِت‌ها ( Sets ) چیستند؟‌ 

سِت‌ها کار شما را برای ذخیره کردن داده‌های غیر‌تکراری راحت می‌کنند! یعنی این‌که شما به راحتی و بدون این‌که نگران باشید چه تعداد مقادیر تکراری دارید، می‌توانید به روند توسعه پروژهٔ خودتان ادامه دهید و مابقی کار را به این یکی نوع از مجموعه‌ها بسپارید. این در صورتی است که شما نمی‌خواهید دائما بررسی کنید که آیا داده‌های تکراری دارید یا نه و با تعریف این نوع، خیالتان آسوده خواهد شد. همچنین داده‌هایی که در این نوع به نمایش درخواهند آمد، به صورت نامنظم هستند! یعنی اینکه اگر شما مقادیر خودتان را به صورت منظم اضافه کرده باشید، خروجی آن چیزی نیست که به صورت منظم خواسته باشید. در واقع می‌توان گفت، Setها؛ داده‌های غیر‌تکراری و نامنظم را در خود نگهداری می‌کنند. 

برای تعریف یک Set به این صورت عمل خواهیم کرد، می‌توانیم به دو صورت عمل کنیم؛ 

  • استفاده از کلاس و تعیین نوع داده 
  • استفاده از کلاس بدون تعیین نوع داده

به اولین مورد، یعنی استفاده از کلاس و تعیین نوع داده می‌پردازیم؛ پس به این صورت عمل خواهیم کرد؛

var setـvar = Set<String>() // Or any data type 

همانطور که مشاهده می‌کنید، ابتدا یک متغییر تعریف خواهید کرد و سپس نام کلاس Set را می‌آورید و در نهایت در بین <> نوع دادهٔ خود را مشخص می‌کنید و سپس پرانتز () را قرار می‌دهید. در حال حاضر، شما یک Set خالی خواهید داشت! چرا که هیچ داده‌ای برای آن در نظر نگرفته‌اید. برای این‌کار به شکل زیر عمل خواهیم کرد؛ 

var set_var = Set<String>() // Or any data type 
set_var.insert("www.iostream.ir")
set_var.insert("www.fanoox.com")
set_var.insert("Tegra CMS") 
set_var.insert("www.ModernCpp.ir")
set_var.insert("Apple")
set_var.insert("Google")
set_var.insert("Apple") 
set_var.insert("Google")
set_var.insert("Microsoft")

// Iterator in the set_var 

for items in set_var {
  print("Items in the set_var collection : ", items)
  /* Items in the set_var collection : www.iostream.ir 
     Items in the set_var collection : www.fanoox.com
     Items in the set_var collection : Tegra CMS
     Items in the set_var collection : www.ModernCpp.ir
     Items in the set_var collection : Apple
     Items in the set_var collection : Google
     Items in the set_var collection : Microsoft
   */
}

برای این‌که بتوانیم داده‌ای یا مقداری را ذخیره کنیم، از متد insert استفاده می‌کنیم که در بالا هم مشاهده می‌کنید. اما نکته‌ای که به احتمال زیاد شما هم متوجه آن شده‌اید، این است که ما دو بار مقدار Google و Apple‌ را ذخیره کرده‌ایم! اما همان‌طور که در تعریف Set گفتیم، در خروجی فقط یک‌بار این مقادیر نمایش داده می‌شوند، حتی اگر به تعداد زیاد بخواهید دادهٔ تکراری وارد کنید! چرا که این نوع (‌ Set ) فقط مقادیر غیر‌تکراری را ذخیره خواهد کرد.

تعریف دیگر آن به این صورت است؛ 

var setـvar : Set = [1,2,3,4,5,6,7,8,9,10]

print(set_var) // Output is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

در این مورد، شما مانند تعیین نوع برای متغییر، نام کلاس Set‌ را بعد از دو نقطه ( که به آن هم کالُن ( : )‌ گفته می‌شود ) آورده و سپس مانند یک آرایه، مقادیر و داده‌های خودتان را در بین دو قُلاب [] می‌نویسید. برای نمایش دادن آن هم کافیست که نام آن را بیاورید، همانند تعریف بالا. این نکته را به یاد داشته باشید که کامپایلر، به صورت ضمنی ( Implicit ) نوع داده را تشخیص داده و نیازی به ذکر نوع داده نخواهید داشت. 

ویژگی‌ها ( Properties ) و متد‌ها

به دست آوردن تعداد اعضا

با استفاده از ویژگی count می‌توانید به تعدا اعضای یک Set دسترسی داشته باشید؛ 

var set_var : Set = [1,2,3,4] 

print(set_var.count) // Output is 4

بررسی خالی بودن یا نبودن Set

و همچنین اگر می‌خواهید خالی بودن یا نبودن را بررسی کنید، isEmpty این امکان را در اختیار شما قرار داده است؛

var set_var : Set = [1,2,3,4,5,6,7,8,9,10]

if set_var.isEmpty {
  print("set_var is empty!") 
}  else {
  print("set_var not empty") // This will run code 
}

اضافه کردن عضو جدید

در حالت عادی نمی‌توانیم به Setهای خودمان عضوی یا داده‌ای اضافه کنیم! در تعریف دوم شما دیدید که ما به صورت مستقیم این کار را انجام دادیم، اما در ادامهٔ برنامه شاید نظرمان عضو شود و بخواهیم عضو را حذف و عضو دیگری را اضافه کنیم؛ برای این منظور از متد insert استفاده خواهیم کرد؛

var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]

celebrities.insert("Jeffrey Preston Bezos") 
celebrities.insert("Sergey Brin")
celebrities.insert("Lawrence Lary Page")  



همان‌طور که مشاهده کردید، ما با استفاده از متد insert می‌توانیم عضو‌های جدیدی را اضافه کنیم. 

حذف یک عضو 

برای این کار ما از متد remove استفاده می‌کنیم؛

var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]

celebrities.remove("Steven Paul jobs") 

print(celebrities) // Output is ["William Henry Bill Gates lll", "Elon Reeve Musk"] 

این متد یک آرگومان دریافت خواهد کرد و همان عضوی است که می‌خواهید حذف شود. 

بررسی وجود داشتن یا نداشتن یک مقدار خاص 

از متد contains برای این منظور استفاده می‌کنیم؛ 

var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]
if celebrities.contains("Elon Reeve Musk") {
  print("Elon Reeve Musk is available in the celebrities") // This will run code
} else {
   print("Elon Reeve Musk is'n available in the celebrities")
}

نکته

متد‌های کار با Set، با خود Set اصلی کاری نداشته و بسته به متد، یک Set‌ جدید برگردانده می‌شود.

گَردش در Set

برای این‌که بتوانیم به تک‌تک اعضای یک Set دسترسی داشته باشیم، از حلقهٔ for استفاده می‌کنیم، به این کار گردش می‌گویند. در جلسهٔ قبل، توضیحی مختصر در این باره‌ داده‌ایم که می‌توانید مطالعه کنید. پس به گردش در Set به این صورت است؛

var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]

for items in celebrities {
  print("Celebrities : ", items) 
  
  /* Celebrities : Steven Paul jobs
     Celebrities : William Henry Bill Gates lll
     Celebrities : Elon Reeve Musk
   */
}

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

مرتب‌سازی 

در حالت پیش‌فرض، نوع Set هیچ مبنایی برای مرتب‌سازی ندارد و داده‌ها را به صورت تصادفی نمایش خواهد داد؛ در صورتی که بخواهید بر اساس ترتیب داده‌ها را نمایش دهید، می‌توانید از متد sorted استفاده کنید؛

var celebrities : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]

for items in celebrities.sorted {
  print("Sorted celebrities : ", items) 
  
  /* Sorted celebrities : Elon Reeve Musk
     Sorted celebrities : Steven Paul jobs
     Sorted celebrities : William Henry Bill Gates lll
   */
}

فقط توجه داشته باشید که این متد باید در حلقه مورد استفاده قرار گیرد. 

ایجاد یک Set جدید با ترکیب دو Set یا ( Union ) 

با استفده از متد union شما می‌توانید یک Set کاملا جدید، ایجاد کنید؛

var celebrities_some_one : Set = ["Steven Paul jobs", "William Henry Bill Gates lll", "Elon Reeve Musk"]
var celebrities_two_some : Set = ["Jeffrey Preston Bezos","Sergey Brin","Lawrence Lary Page"]
var celebrities_final : Set = celebrities_some_one.union(celebrities_two_some)
print(celebrities_final)

ذخیره یک مقدار مشترک ( Intersection ) 

اگر دو Set داشته باشیم و یک مقدار در هر دو یکسان باشد، متد intersection می‌تواند همهٔ مقادیر دیگر را پاک کرده و فقط همان مقدار را در قالب یک ‌Set‌ جدیدی برگرداند؛

var numbers_one : Set = [1,6,3]
var number_two : Set = [5,6,3]
var number_final : Set = number_one.intersection(number_two)
print(number_final) // Output is [6, 3]

همان‌طور که مشاهده کردید، در خروجی مقدار 3 , 6 را خواهیم داشت، چرا که باقی مقدار تکراری نبوده و در نتیجه حذف خواهند شد. 

حذف مقادیر یک Set و مقادیر مشابه ( Subtracting ) 

اگر بخواهیم مقادیر یک Set را به طور کامل حذف کنیم و همچنین اگر مقداری تکراری وجود داشت، آن را هم حذف کرده و فقط Set اول را داشته باشیم، از متد subtracting استفاده خواهیم کرد؛

var numbers_one : Set = [1,6,3]
var number_two : Set = [5,6,3]
var number_final : Set = number_one.subtracting(number_two)
print(number_final) // Output is [1]

مشاهده می‌کنید که خروجی برابر ۱ است! چرا که Set اول فقط مقدار ۱ را دارد و مابقی مقادیر در Set اول و دوم تکرار هستن و در نهایت حذف خواهند شد. 

ایجاد یک Set جدید با مقادیر غیر تکراری ( SymmetricDiffernce ) 

در متد union شما مقادیر غیر‌تکراری را نخواهید داشت و در Set جدیدی که ساخته خواهد شد و یا به طور مستقیم در خروجی نمایش داده می‌شود، فقط یک‌بار مقادیر نمایش داده می‌شوند؛ اما با متد symmetricDifference شما مقادیر دو طرف Set را حذف خواهید کرد و فقط مقادیری که دیگر تکراری نیستند، نمایش داده می‌شود. اجازه بدهید با ذکر یک مثال، این موضوع را شفاف‌تر کنیم؛ 

var numbers_one : Set = [1,6,3]
var number_two : Set = [5,6,3]
var number_final : Set = number_one.symmetricDiffernce(number_two)
print(number_final) // Output is [1,5]

همان‌طور که مشاهده می‌کنید، ما مقادیر ۳ و ۶ را نخواهیم داشت! چرا که در این متد، مقادیر تکراری هر دو Set حذف خواهند شد و داده‌هایی که تکراری نیستند، در یک Set جدید ایجاد می‌شوند. 

 

امیدواریم که این جلسه مورد رضایت شما عزیزان قرار گرفته باشد.

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

 

آموزش زبان برنامه‌نویسی سوئیفت - جلسه هشتم

مواردی که در این جلسه یاد خواهید گرفت: دیکشنری ( Dictionary )

 

دیشکنری‌ها چیستند؟ 

به طور ساده و خلاصه؛ یکی از نوع‌های مجموعه‌ است که مقادیر یا همان داده‌ها را به صورت کلید/مقدار ( key/value ) ذخیره می‌کند و همچنین نامرتب است و داده‌های تکراری را فقط یک‌بار مورد ذخیره! این‌کار به شدت می‌تواند به برنامه‌نویس کمک کند تا راحت‌تر، بهتر و سریع‌تر به داده‌های خود از طریق کلید ( key ) دسترسی داشته باشد و همچنین کُدی خوانا‌تر داشته باشد. برای این‌که این موضوع برای شما عزیزان شفاف‌تر شود و بهتر بتوانید این موضوع را درک کنید، شروع به ایجاد دیکشنری خودمان خواهیم کرد و در ادامه، توضیحات لازم را ارائه خواهیم داد. 

برای ایجاد یک دیکشنری، به چهار صورت می‌توانیم عمل کنیم؛

  • استفاده از کلاس Dictionary و سپاس در بین دو علامت <> کلید و مقدار خود را قرار می‌دهیم <Dictionary<Key, Value که البته باید در نظر داشته باشید،  Key و Value نوع دادهایی هستند که باید قرار گیرند و بعد‌ا مقدار‌دهی بر اساس نوع‌های داده خواهد بود نه مستقیما مقدادهی کنید! مانند؛ <Dictionary<String, Double
  • تعریف یک متغییر و سپس استفاده از الگوی؛‌ ()[String : String ] 
  •   استفاده از روش دوم با این تفاوت که شما می‌بایست، دیکشنری خود را همانند تعریف یک متغییر به صورت صریح بنویسید!
  • شما می‌توانید فقط از [] به صورت مستقیم استفاده کنید و داده‌ها را اضافه کنید، مانند؛ ["var products = ["www.fanoox.com : "MacBook Pro

از اولین مورد شروع خواهیم کرد، پس به این شکل عمل می‌کنیم؛ 

var users_and_passwords= Dictionary<String, String>()

users_and_passwords["Mohammad"] = "!#$#@%#$!#@$"

users_and_passwords["Ali"] = ")+_)(*&^^%" 

users_and_passwords = ["Ali" : "_)(*&^%^&*", "Hamed" : "123456789%$#@!#$^%!$1009876!!$$%!$54321"]

print(users_and_passwords) 

/* ["Ali" : "_)(*&^%^&*", "Hamed" : "123456789%$#@!#$^%!$1009876!!$$%!$54321" ] */

همان‌طور که مشاهده می‌کنید، یک متغییر تعریف کرده و سپس از کلاس Dictionary استفاده کردیم که در بین دو علامت <> ( بزرگ‌تری و کوچک‌تری ) نوع‌هایی که می‌خواهیم از آن‌ها در برنامه‌مان استفاده کنیم، به کار بردیم. شما می‌توانید هم به تنهایی و هم گروهی، مقداردهی را شروع کنید! در قطعه‌کد بالا می‌بینید که خط ۲ و ۳، به صورت تَکی و خط ۴ به صورت گروهی مقداردهی شده است و در نهایت در خط ۵ آن را چاپ می‌کنیم. توجه داشته باشید  که اگر در حالت گروهی بخواهید مقدادهی کنید،‌ مقادیر قبلی از بین خواهند رفت! در حالی که اگر شما به صورت تکی مقداردهی کنید، این اتفاق نخواهد افتاد. 

نکته

اگر به صورت تَکی بخواهید مقداردهی کنید، هیچ اتفاقی برای مقادیر دیگر نخواهد افتاد! اما اگر گروهی مقداردهی کنید، داده‌های قبلی به کل پاک و داده‌های جدید، قرار خواهند گرفت.

دومین نوع تعریف بدون استفاده از کلاس است؛ 

var languages_and_framework = [String : String]()

languages_and_framework["C++"] = "Qt Creator "

languages_and_framework["PHP"] = "Laravel" 

print(languages_and_framework)

/* ["C++" : "Qt Creator ", "PHP" : "Laravel"] */

در سومین حالت تعریف به این شکل عمل خواهیم کرد؛‌

var languages_and_framework : [String : String] = ["C++" : "Qt Creator", "Javascript" : "Angular.js"] 

print(languages_and_framework)

/* ["C++" : "Qt Creator", "Javascript" : "Angular.js"] */

و در نهایت در حالت چهارم اگر بخواهیم دیکشنری خودمان را تعریف کنیم، به این صورت عمل می‌کنیم؛‌

var languages_and_framework = ["C++" : "QT Creator", "PHP" : "Laravel"]

print(languages_and_framework) 

/* ["PHP" : "Laravel", "C++" : "Qt Creator"] 

نکته

در تمامی این مثال‌ها، وقتی داده‌ها را نمایش می‌دهیم، به صورت نامرتب نمایش داده خواهند شد! چرا که همان ابتدا گفتیم، دیکشنری‌ها، نامرتب هستند و این مورد در خروجی داده‌ها هم صِدق می‌کند. 

نحوهٔ دسترسی به داده‌های 

ما می‌توانیم با استفاده کلید ( Key ) به داده‌های مرتبط با آن دسترسی داشته باشیم! به این صورت که شما نام کلیدی را که از قبل انتخاب کردید، در بین دو براکت به همراه اسم دیکشنری خود آورده و سپس علامت تعجب (‌ ! ) را نوشته تا بتوانید مقدار مورد نظر را در دسترس داشته باشید! حتمالا با خود فکر می‌کنید که چرا علامت تعجب؟! اگر از جلسات قبل به خاطر داشته باشید، درمورد متغییر‌های آپشِنال ( Optionals ) صحبت کردیم و گفتیم که برای دسترسی به مقادیر این نوع متغییر‌ها باید از علامت ! استفاده کنیم. در دیکشنری‌ها هم همین موضوع برقرار است و شما برای استفاده از داده‌های آن باید آن‌ها را از حالت آپشنال خارج کنید. به این مثال دقت کنید؛ 

let _name_and_age : [String : UInt]  = ["Mohammad" : 20, "Hamed" : 30] 

print(_name_and_age["Mohammad"]!) // 20

اگر علامت ! را ننویسید، با خطای کامپایلر مواجه خواهید شد. به همین صورت تا هر چند مقدار را که می‌خواهید می‌توانید به آن دسترسی داشته باشید. دقت کنید که اگر بخواهید یک مقدار خاص را در یک متغییر جداگانه ذخیره کنید، نیازی به علامت ! نخواهید داشت؛ 

let _name_and_age : [String : UInt]  = ["Mohammad" : 20, "Hamed" : 30] 

let _age = _name_and_age["Mohammad"]

print(_age["Mohammad"]!) // 20

اگر بخواهید متغییری که جداگانه تعریف کردید، نمایش دهید؛ آن موقع باید حتما از علامت تعجب ( ! ) استفاده کنید. 

اضافه کردن یک مقدار 

برای اضافه کردن یک مقدار، به همان صورتی که در بالا ( تکی اضافه کردن ) تعریف کردیم، استفاده می‌کنیم؛‌ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
numbers[40] = 50 
print(numbers)

/* [20 : 30, 10 : 20, 30 : 40, 40 : 50] */

 

بروز‌رسانی یک مقدار 

اگر بخواهیم داده‌های خود را به روز‌رسانی ( Update ) کنیم، کافیست کلید را آورده و در مقابل، مقدار را اضافه کنیم؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
numbers[40] = 50 
numbers[10] = 100
print(numbers)

/* [20 : 30, 10 : 100, 30 : 40, 40 : 50] */

همان‌طور که مشاهده می‌کنید، کلید ما در این بروز‌رسانی، ۱۰ است است و مقدار ۱۰۰ را به آن اختصاص داده‌ایم! پس دیگر خبری از مقدار ۲۰ نخواهد بود. هم‌چنین شما می‌توانید از متد updateValue از کلاس دیکشنری استفاده کنید. این متد، علاوه بر این‌که مقدار فعلی از یک کلید را برمی‌گرداند، همزمان، مقدار جدید را در همان کلید قرار خواهد داد. این متد دو آرگومان ( Argumant ) دریافت می‌کند که به شرح زیر است؛ 

  1. اولین آرگومان، مقدار جدید است.
  2. دومین آرگومان، کلید است. 

مقدار برگشتی که از این متد، آپشنال خواهد بود! به این مثال دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
numbers[40] = 50 
numbers[10] = 100
if old_number = numbers.updateValue(200, forkey: 20){
  print("Old the number : \(old_number)") // Old the number : 30
}
print(numbers)

/* [20 : 200, 10 : 100, 30 : 40, 40 : 50] */

در قطعه کد بالا مشاهده می‌کنید که از یک شرط استفاده کردیم و مقدار برگشتی از متد updateValue را به متغییر old_number اختصاص داده‌ایم. این مقدار از کلید آن یعنی forkey: 20 گرفته شده است. هنگام چاپ مقدار old_number نیاز به قرار دادن علامت تعجب ( ! ) نیست! این‌کار در همان‌ابتدا در شرط انجام شده است. و در نهایت، در خروجی نهایی کل دیکشنری همان‌طور که می‌بینید، مقدار ۲۰۰ به کلید ۲۰ اختصاص داده شده است. اگر کلید که شما در آرگومان دوم داده باشید، وجود نداشته باشد، پیغام Not Exit و دیکشنری نمایش داده می‌شود، بدون این‌که مقداری حذف شده باشد‌. 

حذف کلید و مقدار

اگر بخواهید کلید و مقدار خود را در حذف کنید، از کلمهٔ کلید nil می‌توانید استفاده کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
numbers[30] = nil
print(numbers)
/* [20 : 30, 10 : 20] */

مشاهده می‌کنید که کلید ۳۰ و مقدار ۴۰ هر دو حذف شدند. شاید با خودتان بگوید چرا کلید هم حذف شده است؟ به این دلیل که اگر مقداری برای کلید نباشد، خود کلید هم حذف خواهد شد؛ چون مقداری ندارد. شما می‌توانید از متد removeValue نیز استفاده کنید! این متد یک آرگومان گرفته و کلید/مقدار را حذف می‌کند. آرگومانی که این متد دریافت می‌کند، کلید است و مقدار برگشتی آن، مقدار حذف‌شده و به صورت آپشنال است ( اگر کلید که شما در آرگومان دوم داده باشید، وجود نداشته باشد، پیغام Not Exit به همراه خود دیکشنری نمایش داده می‌شود. ) به این مثال دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
if remove_value = numbers.removeValue(forkey: 10){
  print("Removed value : \(remove_value)") // Removed value : 20
}
print(numbers)
/* [20 : 30, 30 : 40] */

همان‌طور که مشاهده می‌کنید، مقدار ۲۰ نمایش داده شده که درواقع مقدار حذف شده است. و در آخر هم کل دیکشنری را نمایش می‌دهیم که کلید ۱۰ و مقدار ۲۰ حذف شده‌اند. همچنین شما می‌توانید با استفاده از متد removeAll همهٔ داده‌های دیکشنری را حذف کنید! دقت کنید که فقط داده‌های آن حذف خواهند شد نه خود دیکشنری! به این مثال دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
numbers.removeAll()
print(numbers) // [:]

همان‌طور که مشاهده کردید، فقط داده‌ها حذف شدند و خود دیکشنری هنوز در برنامهٔ ما وجود دارد؛ بنابراین در ادامه می‌توانید داده‌های خود را اضافه کنید. 

گردش در دیکشنری ( Iterating over a dictionary )

شما می‌توانید با استفاده از حلقهٔ for کلید‌ها و مقدار‌ها را دریافت کنید! هر کدام از این آیتم‌ها ( کلید/مقدار ) یک تاپِل هستند. به این مثال دقت کنید تا بهتر این موضوع را متوجه شوید؛‌

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
for (key, value) in numbers{
  print("Key : \(key) and value : \(value)") 
}

/* 
   Key : 10 and value : 20
   Key : 20 and value : 30
   Key : 30 and value : 40

*/

در قطعه کد بالا شما در حلقهٔ for در بین دو پرانتز () به دلخواه دو نام انتخاب کرده که نشان از کلید و مقدار است و در نهایت کلمهٔ کلید in را نوشته و دیکشنری را می‌نویسید. 

به دست آوردن کلید‌ها 

اگر بخواهید فقط و فقط کلید‌های یک دیکشنری را به دست آورید، می‌توانید با استفاده از ویژگی ( Properties‌ ) به نام keys در حلقهٔ for یا به تنهایی استفاده کنید. به این مثال دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
for key in numbers.keys{
  print("Key : \(key)") 
}

/*
 Key : 10
 Key : 20
 Key : 30
*/

// Or print("Keys : \(numbers.keys)") // Output: Keys : [10,20,30]

 

به دست آوردن مقدار‌ها

در مقابل شما می‌توانید با استفاده از ویژگی values فقط و فقط به مقادیر دسترسی داشته باشید. به این مثال دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
for value in numbers.values{
  print("Value : \(value)") 
}

/*
 Value : 20
 Value : 30
 Value : 40
*/

// Or print("Values : \(numbers.values)") // Output: Values : [20,30,40]

 

مرتب‌سازی 

همان‌طور که می‌دانید و همان‌ ابتدا هم گفتیم، دیکشنری‌ها نوعی هستند که نامرتب‌‌اند! یعن داده‌ها را به صورت تصادفی ( Random ) نمایش می‌دهند. اما ما در ادامه مثالی را ذکر خواهیم کرد که شما می‌توانید، هم براساس کلید و هم مقدار، اقدام به مرتب‌سازی داده‌ها کنید. 

مرتب‌سازی بر اساس مقدار

در این حالت ما با استفاده از ویژگی values و سپس متد sorted که همراه خودش دارد، براساس مقدار فقط داده‌ها را مرتب می‌کنیم؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
for sorted_by_value in numbers.values.sorted{
  print("Sorted by value : \(sorted_by_value)") 
}

/*
  Sorted by value : 20
  Sorted by value : 30
  Sorted by value : 40
*/

 

نکته

استفاده از دو حالت بالا صحیح است و اگر شما دو ویژگی values و keys را نیاورید، و فقط متد sorted را به همراه نام دیکشنری بنویسید، اشتباه ‌خواهد بود و از طرف کامپایلر خطا دریافت می‌کنید.

به مثال زیر که اشتباه است دقت کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
print(numbers.sorted()) // Error 

همان‌طور که مشاهده می‌کنید، استفاده از متد بدون ذکر یک از دو ویژگی values و keys از نظر کامپایلر بی‌معنی است و در نتیجه خطا را صادر می‌کند. 

دسترسی به تعدا اعضای دیکشنری 

برای این‌که بتوانید به تعداد اعضای یک دیکشنری دسترسی داشته باشید، از ویژگی count‌ می‌توانید استفاده کنید؛ 

var numbers : [Int : Int]  = [10 : 20, 20 : 30, 30 : 40] 
print("Count the numbers : \(numbers.count)") // Count the numbers : 3 

دقت کنید که منظور از تعدا اعضا، هم کلید و هم مقدار نیست! بلکه یعنی یک کلید و یک مقدار می‌شود یک عضو! در قطعه کد بالا هم مشاهده می‌کنید که ما سه عضو داریم که در خروجی نمایش داده شده است. 

بررسی خالی بودن یا نبودن دیکشنری 

با استفاده از ویژگی isEmpty شما می‌توانید، بررسی کنید که آیا دیکشنریتان خالی است یا نه؟! به این مثال دقت کنید؛ 

var numbers : [Int : Int] = [:]
if numbers.isEmpty{
 print("Dictionary is empty!") // Yes, it is Empty
} else {
 print("Dictionary is not empty!")
}

با استفاده از [:] می‌توانید در همان ابتدا اعلام کنید که دیکشنری شما خالی است. همان‌طور که در خروجی هم می‌بینید، خروجی برابر است با Dictionary is empty است.

امیدواریم که این جلسه مورد رضایت شما قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه  نُهم

مواردی که در این جلسه یاد خواهید گرفت: تاپل‌ها ( Tuples )

تاپِل‌ها چیستند؟‌

تاپل‌ها گروهی از داده‌ها هستند که از داده‌های مختلفی تشکیل شدند و درواقع ترکیبی از مقادیر هستند! در این نوع،‌ برای دسترسی به مقادیر، از کلید/مقدار ( key/value ) استفاده می‌کنیم. این نوع از مجموعه‌ها، می‌توانند هر داده‌ای را در خود ذخیره کنند و نیازی به تعریف نوع داده برای آن‌ها نیست. به زبان ساده؛ تاپل‌ها از این‌که شما بخواهید برای هر نوع داده‌ای یک کلاس جداگانه تعیین کنید (‌ مانند Set )، جلوگیری می‌کند و مجموعه‌ای از داده‌های مختلف را برای شما فقط در یک متغییر ذخیره می‌کند و در ادامه می‌توانید از آن استفاده کنید.

تعریف یک تاپل 

برای این‌کار، ابتدا یک متغییر تعریف کرده ( کلمات کلید let, var ) یک نام انتخاب کرده و سپس در بین دو پرانتز () داده‌های خود را با کاما ( , ) از هم جدا می‌کنید؛ 

let ـfamily = ("Mohammad", 20, 1378, "Esfahan-Felavarjan") 

همچنین شما می‌توانید بخشی از داده‌‌های یک تاپل را در یک متغییر دیگر ذخیره کنید و یا به اصطلاح بُرش بزنید! به این مثال دقت کنید؛

let ـfamily = ("Mohammad", 20, 1378, "Esfahan-Felavarjan") 

let (first_name, age, birthday, _) = family 

print("FirstName is : \(ـfirst_name)") // FirstName is : Mohammad

اگر دقت کرده باشید، در آخرین تعریف یک متغییر، بجای نام ما از آندِرلاین ( ـ ) استفاده کردیم! دلیل آن هم این است که اگر مقداری را نخواهیم، از این علامت استفاده می‌کنیم. به عنوان مثال؛‌ مقدار رشته‌ای Esfahan-Felavarjan را نادیده گرفتیم و با علامت ( ـ ) گفتیم که مقدار آخر را نادیده بگیر! اگر این‌کار را نکنید، خروجی به شما نمایش داده نخواهد شد و با خطای کامپایلر روبرو خواهید شد. 

نکته

دقت داشته باشید که شما اگر بخواهید بخشی از داده‌های تاپل را داشته باشید و در یک متغییر ذخیره کنید، دو راه بیشتر ندارید؛ یا این‌که همهٔ داده‌ها را دریافت کنید، مانند مثال زیر؛

let ـfamily = ("Mohammad", 20, 1378, "Esfahan-Felavarjan") 

let (first_name, age, birthday, address) = family 

print("FirstName is : \(ـfirst_name)") // FirstName is : Mohammad

یا این‌که با علامت ( ـ )، هر کدام از داد‌ه‌ها را که مد‌نظر شما نبود، نادیده گرفته و در نتیجه ذخیره نکنید؛

 

let ـfamily = ("Mohammad", 20, 1378, "Esfahan-Felavarjan") 

let (first_name, ـ , birthday, ـ) = family 

print("FirstName is : \(ـfirst_name)") // FirstName is : Mohammad

اما دقت داشته باشید که شما به هیچ‌وجه نمی‌توانید با اختیار خود یکی از مقادیر را نادیده گرفته ( متغییر برای آن در نظر نگیرید ) و یا این‌که از علامت گفته شده، استفاده نکنید! شما به هر حال باید از یکی از این دو روش استفاده کنید. 

دسترسی به اعضای با استفاده از شماره موقعیت ( Index )‌

این‌کار به صورتی جذاب انجام می‌شود! در این نوع از دسترسی، براکت (‌ [] ) خبری نخواهد بود و شما فقط با آوردن موقعیت ( Index ) می‌توانید به مقدار تاپل دسترسی داشته باشید؛ 

let ـfamily = ("Mohammad", 20, 1378, "Esfahan-Felavarjan") 

print("FirstName is : \(_family.0)") // FirstName is : Mohammad
print("Age is : \(_family.1)") // Age is : 20 

همان‌طور که مشاهده کردید، با آوردن شماره موقعیت، می‌توانید به مقدار آن دسترسی داشته باشید. 

دسترسی به اعضای با استفاده از نام 

شما همچنین می‌توانید با استفاده از نامی که در ابتدای تعریف یک تاپل استفاده می‌کنید، با همان نام،  به اعضای آن دسترسی داشته باشید؛

let ـfamily = (first_name: "Mohammad", age: 20, birthday: 1378, address: "Esfahan-Felavarjan") 

print("FirstName is : \(_family.first_name)") // FirstName is : Mohammad
print("Age is : \(_family.age)") // Age is : 20 

همان‌طور که مشاهده کردید، شما می‌توانید برای مقادیر خود نام هم تعیین کنید و در ادامه با استفاده از همان نام، به مقدار آن دسترسی داشته باشید ( همانند دیکشنری ). بنابر‌این اگر در جایی از پروژهٔ خود نیاز به مقدار‌های مختلفی داشتید و نخواستید که از کلاس‌ها و نوع‌های دادهٔ متفاوت استفاده کنید، می‌توانید از تاپل‌ها برای این منظور استفاده کنید. 

امیدواریم که از این جلسه مورد رضایت شما قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه  نُهم

مواردی که در این جلسه یاد خواهید گرفت: توابع ( Functions‌ )

 

توابع چیستند؟‌

این چیزی را که می‌گوییم، چند لحظه تصور کنید و دوباره به خواندن این مطلب ادامه دهید! فرض کنید پروژه‌ای را شروع کردید و در بخشی از پروژهٔ خودتان، متوجهٔ این شدید، بخشی از کد نیاز به تکرار در جای دیگر دارد... از نظر شما، این کار تکرار کُد؛ بیهوده و بی‌معنی است. پس راه‌حل چیست؟ توابع، یکی از روش‌های جلوگیری از این کار‌هاست! گفتیم یکی از روش‌ها، چرا که روش دیگری نیز وجود دارد که عهده‌دار آن کلاس‌ها هستند. توابع به شما کمک می‌کنند که کدهای کمتری بنویسید و بیشتر استفاده کنید! شما با یک‌بار نوشتن یک قطعه کد، می‌توانید در ادامهٔ پروژهٔ بی‌نهایت از آن قطعه کد استفاده کنید! این همان کاریست که توابع انجام می‌دهند. از جلمه مزایای استفاده از توابع می‌توان به موارد زیر اشاره کرد؛

  • جلوگیری از تکرار کدها یا همان قابلیت استفاده مجدد که می‌توانیم یک‌بار یک تابع را نوشته و چندین بار در جاهای مختلف برنامه از آن استفاده کنیم
  • سرعت بیشتر 
  • جدا نگه‌داشتن بخش‌های مختلف یک برنامه ( از لحاظ منطقی و همچنین از دید برنامه‌نویسی کاری منطقی نیست که یک پروژه را به بخش‌های مختلفی تقسیم نکنیم و همهٔ کار‌ها را به یک بخش محول کنیم ) 
  • خوانایی بیشتر برنامه 
  • خطایابی آسان‌تر می‌شود 

و مواردی دیگر ... 

البته مواقعی هم هستند که توابع باعث می‌شوند که سرعت اجرای برنامه کاهش پیدا کند! مانند موقعی که شما به توابع پارامتر می‌دهید، و در یک فراخوانی ( Calling ) آرگومان‌های خود را به آن ارسال می‌کنید، سرعت اجرا پایین می‌آید، اما موقعی که کد‌ها را مستقیما می‌نویسید، حافظه درگیر فراخوانی و گرفتن ورودی نمی‌شود و مستقیم، روی فراخوانی و اجرای کدها تمرکز می‌کند. 

 

نحوهٔ تعریف یک تابع 

ابتدا به نحوهٔ تعریف یک تابع می‌پردازیم و در ادامه هر بخش را توضیح خواهیم داد؛ 

func FunctionName ( Parameters ) -> ReturnType {
  // Statements
  
  return parameters
}

همان طور که مشاهده می‌کنید، تعریف کلی یک تابع در سوئیفت به این شکل است. از کلمهٔ کلیدی func شروع می‌کنیم. این کلمهٔ کلید که کوتاه‌ شده‌‌ی ( function )‌ به معنای تابع است، به کامپایلر اطلاع می‌دهد که برنامه‌نویس می‌خواهد یک تابع تعریف کند! درواقع این نشانگر تعریف یک تابع است. بعد از این کلمهٔ کلید باید یک نام برای تابع خودتان انتخاب کنید. بدون نام شما چطور می‌خواهید به تابع خود دسترسی داشته باشید؟‌ در انتخاب نام آزاد هستید، اما علاوه‌ بر رعایت نکات نامگذاری توابع، نام تابع شما باید نمایانگر کاری است که تابع شما قرار است انجام دهد. بعد از نام، شما باید در بین دو پرانتز () پارامتر‌های ( Parameters )‌ را مشخص کنید! پارامتر‌ها، متغیر‌هایی هستند که در هنگام تعریف تابع، مشخص می‌شوند و برای گرفتن مقداری خاص از کاربر استفاده می‌شوند. بعد از مشخص کردن پارامتر‌ها، باید نوع برگشتی ( ReturnType ) را مشخص کنید. فرض کنید می‌خواهید عمل فیلتر را روی تصویر انجام دهید! اگر بخواهید بعد از اعمال فیلتر روی تصویر توسط تابع، تصویر فیلتر‌شده را در اختیار داشته باشید، نیاز خواهید داشت که آن را در قالب خاصی به تابع برگردانید! و اگر فقط تصویر فیلتر‌شده را خواستید نمایش بدهید، به طور مستقیم و بدون نوع برگشتی می‌توانید این‌کار را انجام دهید. منظور از قالب خاص، همان نوع داده‌ای است که به تابع برگردانده می‌شود. در انتها، شما دربین دو آکولاد {}، می‌توایند دستورات خود را بنویسید. فراموش نکنید که در آخر دستورات، باید return parameters را بنوسید! چرا که شما اگر نوع برگشتی را مشخص کرده باشید، باید مقداری هم برگشت دهید و این‌کار با استفاده از این دستور امکان‌پذیر است. البته به‌جای parameters باید دادهٔ مرتبط با نوع برگشتی را بنویسید. توضیحات کافیست؛ بیاید یک مثال عملی را با هم ببینیم؛ 

func getWebSite(website_name: String) -> String {
   
    let platform_name_and_website_name = "www.fanoox.com + " + first_name = " :) -> Perfect!"
    
    return platform_name_and_website_name 
}

print(getWebSite(website_name: "www.iostream.ir") // www.fanoox.com + www.iostream.ir = :) -> Perfect

 همان‌طور که مشاهده کردید، شما یک اسم برای پارامتر انتخاب می‌کنید و به دنبال آن نوع داده را انتخاب می‌کنید. مانند؛ website_name: String و نوع برگشتی را هم که ملاحضه می‌کنید، با علامت <- و سپس نوع دادهٔ مورد‌نظر ( در این مثال؛ String ) مشخص می‌کنید. بعد از آن شما می‌توانید در بین دو آکولاد باز و بسته {}، کد‌های خود را در درون آن‌ها بنویسید و در آخر فراموش نکنید باید یک مقداری را برگشت دهید که با دستور return و مقدار برگشتی (‌ در این مثال؛ platform_name_and_website_name‌ ) را تعیین کنید. دقت کنید که مقداری را که برگشت می‌دهید باید با نوع داده‌ای که در تعریف تابع مشخص شده است، یکسان‌ باشد. برای فراخوانی یا همان صدا زدن تابع، همان‌طور که می‌بینید، باید فقط اسم تابع را بیاورید و بعد از آن اگر پارمتری الزامی بود، به آن بدهید. نام پارارمتر را هم باید حتما با نام باشد! ( "website_name: "www.iostream.ir ) که غیر از این باشد، کامپایلر از شما خطا خواهد گرفت. 

همچنین شما می‌توانید یک تابع بدون پارامتر و با نوع برگشتی داشته باشید و یا برعکس! یعنی بدون پارامتر و نوع برگشتی. ابتدا یک تابع با نوع برگشتی و بدون پارامتر مثال خواهیم زد؛ 

func getWebSite() -> String {
   
    let platform_name = "www.fanoox.com -> :) -> Perfect!"
    
    return platform_name 
}

print(setWebSite()) // www.fanoox.com -> :) -> Perfect

همان‌طور که مشاهده کردید، ما می‌توانیم یک تابع بدون پارامتر و در عین حال با نوع برگشتی داشته باشیم. در مقابل اگر هیچ‌کدام از این موارد را نخواهیم؛ یعنی بدون پارارمتر و نوع برگشتی، به این صورت عمل خواهیم کرد؛

func getWebSite() {

    print("www.fanoox.com -> :) -> Perfect!")
}

getWebSite() // www.fanoox.com -> :) -> Perfect

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

پارامتر‌های چندگانه

فرض کنید می‌خواهید یک ماشین حساب طراحی و کد‌نویسی کنید! اگر بخواهید از توابع استفاده کنید، نیاز به این خواهید داشت که دو عدد به همراه یک آپریتر ( Operator ) به تابع ارسال کنید. در این صورت ما از پارامتر‌های چندگانه استفاده می‌کنیم. یعنی شما می‌توانید تا بی‌نهایت، پارارمتر در هنگام تعریف تابع، بنویسید. بیاید یک ماشین حساب کوچک، با هم طراحی کنیم؛ 

func Calculator(number_one: Double, number_two: Double, operator_ch: Character) -> Double {
  
  if operator_ch == "+" {
      return number_one + number_two 
  } else if operator_ch == "-" {
      return number_one - number_two
  } else if operator_ch == "*" {
      return number_one * number_two
  } else if operator_ch == "/" {
      return number_one / number_two
  } else {
      return 0
  }
}

print(Calculator(number_one: 10, number_two: 30, operator_ch: "+")) // 40
                                                                             // 40 + 30 = Chelsea
print(Calculator(number_one: 10, number_two: 20, operator_ch: "+")) // 30 

به همین سادگی ما توانسیتم یک ماشین حساب کوچک طراحی کنیم! شما می‌توانید حتی با اضافه کردن ویژگی‌های جدید‌تر، آن را گسترش دهید. اما نکتهٔ مهم‌تر از آن، پارارمترهای چندگانه‌ هستند که مشاهده کردید. ما در هنگام تعریف تابع ماشین‌حساب،‌ از سه پارارمتر استفاده کردیم! دو عدد و یک کارکتر. دو عدد که کاربر وارد کرده و کارکتر هم همان یک از ۴ آپریتر (‌+,-,/,* )‌ هستند که درواقع چهار عمل اصلی در محاسبات ریاضی را انجام می‌دهند. همچنین شما می‌توانستید بدون این‌که بخواهید نوع برگشتی را مشخص کنید، مستقیم نتیجه را نمایش دهید؛

func Calculator(number_one: Double, number_two: Double, operator_ch: Character) {
  
  if operator_ch == "+" {
      print(number_one + number_two)
  } else if operator_ch == "-" {
      print(number_one - number_two)
  } else if operator_ch == "*" {
      print(number_one * number_two)
  } else if operator_ch == "/" {
      print(number_one / number_two)
  } else {
      print(0)
  }
}

Calculator(number_one: 10, number_two: 30, operator_ch: "+")) // 40
                                                                             // 40 + 30 = Chelsea
Calculator(number_one: 10, number_two: 20, operator_ch: "+")) // 30 

می‌توانید تا بی‌نهایت پارامتر اضافه کنید، اما دقت کنید که این‌کار باعث اشغال منابع از حافظه می‌شود، پس به تعداد مورد نیاز، پارامتر اضافه کنید.  

نام پارامتر‌ها و برچسب‌‌های آرگومان‌ها 

در حالت پیش‌فرض اگر تابعی را تعریف کنید و پارامتری را هم برای آن مشخص کنید، در هنگام فراخوانی ( Calling ) موظف هستید که اسم نام متغییر در پارامتر که برچسب خوانده می‌شود را هم بیاورید و سپس مقدار را در مقابل آن بنویسید؛ 

func getFirstName(first_name: String) -> String{
  
   return "FirstName is : \(first_name)"  
}
func getLastName(last_name: String) -> String {
  
  return "LastName is : \(last_name)"
}

func getStyleMe() -> String{
  
   return "  ): + :) with code = :) -> Perfect!  " 
}
print(getFirstName(first_name: "Mohammad"), getLastName(last_name: " Abasi"), getStyleMe()))
 
// Mohammad Abasi ): + :) with code = :) -> Perfect!

همان‌طور که مشاهده کردید، در هنگام فراخوانی موظف به نوشتن برچسب نام متغییر‌ها در هنگام تعریف تابع نیز می‌باشید! ( در این مثال، first_name و last_name‌ )  البته این حالت پیش‌فرض حالت سوئیفت است و شما می‌توانید از این حالت پیش‌فرض استفاده نکنید ( در ادامه بیشتر توضیح خواهیم داد ) و در این مورد سوئیفت، کاملا دست شما را باز نگه داشته است. 

اگر بخواهید از دو برچسب در پارامتر‌ها استفاده کنید و یکی از برچسب‌ها فقط نقش گرفتن مقدار را داشته باشد، به این صورت می‌توانید عمل کنید؛ 

func getFullName(name first_name: String, last last_name: String) -> String {
    return "FirstName is : \(first_name) and LastName is : \(last_name)"
}

print(getFullName(name: "Mohammad", last: "Abasi"))

// FirstName is : Mohammad and LastName is : Abasi

برچسب‌های اولیه ( name, name ) همان نقش پیش‌فرض را برای تابع بازی می‌کند و مقدار‌های رشته‌ای Mohammad و Abasi در برچسب‌های last_name و first_name ذخیره می‌شوند. ا

گر نخواستید از برچسب‌ها استفاده کنید و درواقع آن‌ها را مزاحم دانستید؛‌ می‌توانید از علامت آنِدرلاین‌ ( ـ ) برای این منظور استفاده کنید؛‌ 

func getFullName(_ first_name: String, _ last_name: String) -> String {
    return "FirstName is : \(first_name) and LastName is : \(last_name)"
}

print(getFullName("Mohammad", "Abasi"))

// FirstName is : Mohammad and LastName is : Abasi

دقت کنید که حتما شما باید یک نام یا همان برچسب دوم برای ذخیره شدن مقدار آرگومان ( در این مثال؛ first_name, last_name ) بنویسید. همان‌طور هم که ملاحضه کردید، در هنگام فراخوانی تابع، ما دیگر از برچسب استفاده نکردیم! بلکه با گذاشتن علامت آندِرلاین ( ـ ) کامپایلر برچسب‌ها را نادیده گرفته است. 

پارامتر‌های پیش‌فرض

شما می‌توانید از مقادیر پیش‌فرض برای توابع خود استفاده کنید! اگر تابعی را که تعریف می‌کنید، مطمعن نیستید که کاربر مقداری را وارد می‌کند یا نه، می‌توانید از مقادیر پیش‌فرض مورد‌نظر خود برای این منظور استفاده کنید؛ 

func getFullName(_ first_name: String = "Mohammad", _ last_name: String = "Abasi") -> String {
    
    return first_name + " " + last_name
}

print(getFullName()) // Mohammad Abasi

print(getFullName("Mehdi")) // Mehdi Abasi

print(getFullName("Hamed", "Doosti")) // Hamed Doosti

همان‌طور که مشاهده کردید، شما می‌توانید از یک یا چند مقدار ( بستگی به نیاز ) به صورت پیش‌فرض استفاده کنید که اگر احیانا کاربر، مقداری را وارد نکرد، کامپایلر از مقدار پیش‌فرض که تعیین کردید، استفاده می‌کند. در فراخوانی اول مشاهده می‌کنید که چون برای هر دو پارامتر first_name و last_name مقداری مشخص تعیین کردیم، بدون هیچ مسئله‌ای، خروجی برای ما نمایش داد می‌شود و در فراخوانی‌های ("getFullName("Mehdi نگران پارامتر دوم نیستیم! چرا که مقدار پیش‌فرض Abasi را دارد. و همچنین ("getFullName("Hamed", "Doosti هم مقادیر آن جایگزین با مقادیر Mohammad و Abasi می‌شود. 

 

پارامتر‌های متغییر ( Variadic Parameters )

شاید با خود بگویید؛ پارامتر‌های متغییر دیگر چیستند؟! در اکثر مواقع ما می‌خواهیم فقط و فقط با یک پارامتر در یک تابع، تا بی‌نهایت بتوانیم هنگام فراخوانی، مقادیر ارسال کنیم! در برخی از زبان‌های برنامه‌نویسی این امکان فراهم شده است و سوئیفت هم یکی از این‌ زبان‌هاست. اگر یک تابع داشته باشید که نام مشتریان را دریافت کند و آن‌ها را در دیتابیس ( پایگاه داده ) ذخیره کند، در این صورت شما نمی‌توانید از هزاران پارامتر برای این منظور استفاده کنید و کاری غیر منطقی است. بنابر‌این با استفاده از الگوی زیر، شما می‌توانید با یک پارامتر، تا بی‌نهایت نام مشتری به تابع ارسال کنید؛ 

var database = Array<String>()
func storeCustomers(_ customer: String ... ) {
    database = customer
}
func getCustomer(_ index: Int = 0) -> String {
    return database[index]
}
storeCustomers("Mohammad", "Mehdi", "Ahamad", "Nahid", "Zhara", "Ali", "Hamed", "Daryoos", "Karim")

print(getCustomer(1))

همان‌طور که مشاهده می‌کنید، در تابع storeCustomers پارامتر ... customer: String _ استفاده کردیم که بیانگر تابعی با پارامتر‌های متغییر است! این پارامتر همانند یک آرایه عمل می‌کنید و تنها تفاوت آن غیرقابل تغییر بودن و به اصطلاح فقط خواندنی (‌ Read-Only ) است. اگر سعی کنی که customer را تغییر دهید، با این خطا مواجه خواهد شد؛‌ cannot assign to value: 'customer' is a 'let' constant، که نشانگر آن است، این آرایه ( در این مثال؛ customer ) یک ثابت یا همان let است و قابل تغییر نیست. 

سه نقطه‌ای ( ... ) که مشاهده می‌کنید، به کامپایلر این پیغام را می‌رساند که این تابع قرار است بیش از یک مقدار دریافت کند و یا همان مقادیر متغییر! پس آن را فراموش نکنید. در قطعه کد بالا، ما یک شبیه‌سازی ذخیره و بازیابی نام کاربر را انجام داده‌ایم که شما می‌توانید با خلاقیت خودتان، چیزی بهتر و خارق‌العاده‌تر بنویسید! پس با این روش می‌توانید پارامتر‌های متغییر ارسال کنید و نگران این نباشید که هزاران پارامتر تعریف کنید؛ به این نکته‌ هم دقت کنید که حتما حتما در این نوع تعریف تابع، باید از آندِرلاین (‌ - ) استفاده کنیم در غیر این‌صورت با خطای کامپایلر مواجه خواهید شد. 

نکته

شما نمی‌توانید بیش از یک variadic parameters در تابع خود داشته باشید! فقط و فقط مجاز به تعریف یک variadic parameter هستید. 

 

پارامتر با ارجاع 

اگر شما یک متغییر خارج از تابع داشته باشید و بخواهید همان متغییر را به تابع بفرستید، عملا مقدار کُپی شده است! این یعنی این‌که اگر تغییری در متغییر داخل تابع که به  عنوان متغییر داخلی ( Local ) شناخته می‌شود؛ صورت گیرد،  متغییر سراسری ( Global ) هیچ تغییری نمی‌کند! چرا که فقط مقدار کپی شده است نه ارجاع! اگر بخواهیم همان متغییری را که به تابع ارسال می‌کنیم، همزمان با تغییر متغییر در تابع،‌ تغییر کند، به این صورت عمل خواهیم کرد؛ 

var first_name : String = "Mohammad"


func Local(_ first_name: inout String) -> String{
   
   first_name = "Mehdi"
   return first_name // Current value 
}

func Global() -> String {
    
    return first_name // Value has changed 
}


print(Local(&first_name)) // Mehdi 
print(Global()) // Mehdi 

همان‌طور که مشاهده کردید، ابتدا یک متغییر سراسری ( "var first_name : String = "Mohammad ) تعریف کرده و سپس دو تابع به نام‌های Local و Global ایجاد کردیم. اولین تابع یعنی؛ Local برای دریافت مقدار از طرف کاربر است و اگر توجه کرده باشید ما در پارامتر تابع از کلمهٔ کلید inout استفاده کرده‌ایم! این کلمهٔ کلیدی برای دریافت مقدار با ارجاع است و حتما باید آن را بعد از نام پارامتر و دو نقطه ( : ) بیاورید و در نهایت نوع داده را مشخص کنید. در مقابل تابع Global است که مقدار تغییر داده شدهٔ متغییر سراسری را تغییر می‌دهد ( همان متغییر که بالاتر از تمام توابع نوشته شده است ). در هنگام فراخوانی تابع دقت داشته باشید که اگر از ارجاع ( کلمهٔ کلید inout ) استفاده کرده باشید، باید حتما از آپریتر & قبل از فرستادن متغییر به تابع استفاده کنید! چرا که قرار است آدرس متغییر را به تابع ارسال کند و در این صورت است که می‌توانیم عمل ارجاع و تغییر متغیر سراسری را انجام دهیم. هنگامی که شما متغییر first_name& را به این شکل به تابع ارسال می‌کنید، درواقع آدرس را ارسال می‌کنید و آدرس حافظهٔ متغیر داخل تابع، با متغییر سراسری یکی است! وقتی متغییر داخلی تغییر کند، متغییر سراسری هم تغییر می‌کند. در فراخوانی توابع هم مشاهده می‌کنید که علاوه بر این‌که متغییر داخلی مقدار تغییر کرده (‌ تابع Local )، متغییر سراسری هم مقدارش تغییر کرده است ( تابع Global ). بنابر‌این ما می‌توانیم به این صورت عمل ارجاع و تغییر متغییر از بیرون تابع را انجام دهیم. 

نکته

شما نمی‌توانید از مقادیر پیش‌فرض در این نوع تعریف تابع استفاده کنید و همچنین هم مجاز به استفاده از مقادیر متغییر ( variadic parameter ) نخواهید بود. 

 

استفاده از نوع‌های تابعی

سوئیفت، قابلیت‌های جالب و در عین حال ساده دارد! یکی از این قابلیت‌ها نوع تابعی است! ما اگر می‌خواستیم یک متغییر معمولی تعریف کنیم، به این شکل عمل می‌کردیم؛ 

var number : Double = 20.0

 حال ما می‌توانیم یک متغییر با حالت تابع داشته باشیم! به این مثال دقت کنید؛‌

func addition(number_one: Double, number_two: Double) -> Double {
    
    return number_one + number_two
}

let _addition_function : (Double, Double) -> Double = addition

print(_addition_function(10.0,10.0)) // 20.0

احتمالا شما هم مثل عاشق پیچیدگی هستید! اینطور نیست؟! در قطعه کد بالا تابع را تعریف کرده‌ایم که عملا کاری با آن نداریم! ما به متغییر تابعی‌مان _addition_function کار خواهیم داشت و می‌خواهیم آن را موشکافی کنیم! در ابتدا شما می‌توانید از کلمهٔ کلید let و یا var استفاده کنید و سپس با دو نقطعه ( : ) که به آن کالُن هم گفته می‌شود، در بین دو پرانتز () نوع‌ داده‌هایی را که در پارامتر تابع تعریف کردید، می‌نویسید. و سپس همانند نوع برگشتی در تابع ( Double <- ) باید بعد از پرانتز بسته شده (‌ Double, Double ) آن را بنوسید و سپس تابعی را که از قبل تعریف کردیم به آن بدهیم! توجه کنید فقط و فقط نام تابع کافیست و نیازی به پرانتز نیست. الان شما متغییر با حالت تابع‌ماننده دارید و می‌توانید از آن استفاده کنید. هنگامی که متغییر خود را فراخوانی می‌کنید، باید آرگومان‌های الزامی را به آن بدهید؛ همانند مثال بالا ( (addition_function(10.0, 10.0 ). نکتهٔ دیگر که وجود دارد این است که دیگر نیازی نیست، نام پارامتر‌ها را هم برای مقدار‌دهی بیاورید! در صورتی که با تعریف یک تابع معمولی، شما موظف بودید که نام پارامتر‌ها هم برای مقداردهی بنویسید. 

توابع تودرتو ( Nested Functions )

ما می‌توانیم توابعی تودرتو داشته باشیم که عملیات خاصی را برای ما انجام دهند؛‌ 

func NestedFunctions(_ name: String) -> (String) -> String{
    
   func lastNameOne(last_name_one: String) -> String { return "Last Name is One : \(last_name_one)"}
   func lastNameTwo(last_name_two: String) -> String { return "Last Name is Two : \(last_name_two)"}
   func Error(error: String ) -> String {return "Error is : \(error)"}
   if name == "Mohammad" {
       return lastNameOne
   } else if name == "Mehdi" {
       return  lastNameTwo
   } else {
     return Error
   }
}
print(NestedFunctions("Mohammad")("Abasi")) 

// or 

var _function = NestedFunctions("Mehdi")

print(_function("Abasi"))

let  funct = NestedFunctions("Hamed")

print(funct("This is not name!"))

در قطعه کد بالا، ابتدا ما یک تابع به NestedFunctions تعریف کرده و سپس یک پارامتر ( name : String ـ ) ایجاد کردیم. نوع‌های برگشتی را شاید تعجب کرده باشید! اما کاملا ساده هستند! اولین آن‌ها ( ( String ) <- ) اصلا نوع برگشتی نیست! بلکه این نوع‌ها، برای پارامتر‌های توابع داخلی هستند ( lastNameOne, lastNameTwo ) شما می‌توانید تا بی‌نهایت پارامتر اضافه کنید ( دقت کنید به همان تعداد پارامتر که در تابع خارجی برای توابع داخلی اضافه می‌کنید، به همان تعداد پارامتر هم باید برای خود توابع بنویسید ).به همین خاطر هم است که با درون پرانتز این نوع داده‌ها را نوشتیم تا با نوع برگشتی، اختلالی ایجاد نکند. و در نهایت نوع برگشتی ( String <- ) برای برگرداندن مقدار برگشتی توابع داخلی است! در واقع کار تابع NestedFunctions برگرداندن یک تابع است! در بدنهٔ تابع NestedFunction دو تابع داخلی تعریف کردیم ( lastNameOne, lastNameTwo ) که البته بسته به کار شما، تابع می‌تواند در یک خط یا چند خط نوشته شود. اگر به دقت نگاه کرده باشید می‌بییند که توابع داخلی فقط یک پارامتر دارند که یکسان با پارامتر در تابع NestedFunctions است. بنابراین اگر خواستید پارامتر‌های بیشتری اضافه کنید، باید هر دو پارامتر‌ها را تغییر دهید! به این صورت؛ 

func NestedFunctions(_ name: String) -> (String,Int) -> String{
    
   func lastNameOne(last_name_one: String, age: Int) -> String { return "Last Name is One : \(last_name_one) and Age is : \(age)"}
   func lastNameTwo(last_name_two: String, age: Int) -> String { return "Last Name is Two : \(last_name_two) and Age is : \(age)"}
   func Error(error: String, status_code: Int) -> String {return "Error is : \(error) and Status of code : \(status_code)"}
   if name == "Mohammad" {
       return lastNameOne
   } else if name == "Mehdi" {
       return  lastNameTwo
   } else {
     return Error
   }
}
print(NestedFunctions("Mohammad")("Abasi", 20)) 

// or 

var function = NestedFunctions("Mehdi")

print(function("Abasi", 18))

let  funct = NestedFunctions("Hamed")

print(funct("This is not name!",440))
/*

 Last Name is One : Abasi and Age is : 20
 Last Name is Two : Abasi and Age is : 18
 Error is : This is not name! and Status of code : 440

*/

همان‌طور که مشاهده کردید، می‌توانید پارامتر‌های مورد‌نیازتان را هماهنگ با پارامتر‌های توابع داخلی تعریف کنید. مورد بعد نوع برگشتی تابع داخلی است که کاملا باید با نوع برگشتی مشخص شده در تابع خارجی مطابقت داشته باشد و در نهایت در بدنهٔ تابع داخلی می‌توانید دستورات خود را بنویسید و در آخر داده‌‌یم مورد‌نظر را با استفاده از return برگردانید. در خطوط بعد دستورات شرطی را خواهیم داشت که بر اساس پارامتر name کار می‌کنند! اگر مقدار name برابر با رشتهٔ Mohammad باشد، تابع lastNameOne را برمی‌گردانیم و اگر مقدار آن برابر با رشتهٔ Mehdi باشد، تابع lastNameTwo را برمی‌گردانیم. اگر مقدار name با هیچ‌کدام از رشته‌های گفته شده، تطابق نداشته باشد، تابع Error برگشت داده می‌شود. دقت کنید که برای برگشت یک تابع، فقط نام آن را می‌آوریم و نیازی به پرانتز نیست. 

برای فراخوانی هم شما به دو صورت می‌توانید عمل کنید؛ از آنجا که مقداری که NestedFunctions برمی‌گرداند، یک تابع است، پس باید به تابع داخلی هم دسترسی داشته باشیم! به دو روش می‌توانیم این‌کار را انجام بدهیم؛ روش اول به این شکل است؛ 

print(NestedFunctions("Mohammad")("Abasi", 20)) 

یعنی همزمان با دادن پارامتر به NestedFunctions، همان لحظه به صورتی که می‌بینید، در بین دو پرانتز () آرگومانت‌های تابع داخلی را هم بدهید (Abasi", 20" ). 

یا یک متغییر تعریف کرده و تابع داخلی را از NestedFunctions گرفته و به متغییر انتساب دهید؛ 

var function = NestedFunctions("Mehdi")

print(function("Abasi", 18))

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

 

امیدواریم که این جلسه مورد رضایت شما قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه  دهم 

مواردی که در این جلسه یاد خواهید گرفت: توابع بی‌نام (‌ Closures ) و نو‌ع‌های شمارشی

 

توابع بی‌نام ( Closures ) چیستند؟‌

به زبان ساده، توابعی هستند که نامی ندارند! این توابع در واقع به یک متغییر انتساب داده می‌شوند و بعد از آن مورد استفاده قرار می‌گیرند. 

سوال؛‌ تفاوت بین این توابع با توابع معمولی چیست؟ 

پاسخ؛ اگر در روند پروژه‌تان بخواهید که تابعی داشته باشید که فقط و فقط یک‌بار اجرا شده و پس از آن دیگر استفاده از آن نداشته باشید و یا بخواهید که یک تابع جزئی از کد شما نباشد، می‌توانید از توابع بی‌نام استفاده کنید. 

در واقع این نوع توابع، از آنجایی که نامی ندارند، باید به یک متغییر انتساب داده شوند تا بتوان آن‌ها را مورد استفاده قرار داد. اجازه بدهید که با یک مثال، به کنجکاوی شما پاسخ دهیم! در حالت کلی، Syntax ( نحو ) کلی تعریف یک تابع بی‌نام به این شکل است؛ 

{ (Parameters) -> ReturnType in 
    
    // Statments
}

همان‌طور که مشاهده می‌کنید، حالت کلی تعریف یک تابع بی‌نام به این صورت است. ابتدا شما باید دو آکولاد {} تعریف کنید که دستورات شما داخل این بدنه قرار می‌گیرند و سپس باید نوع دادهٔ برگشتی را تعیین کنید. نکتهٔ مهمی که وجود دارد، کلمهٔ کلیدی in است. این کلمهٔ کلید مشخص می‌کند که پارامتر‌های که به تابع می‌دهید، باید از هم جدا شوند! درواقع در حالت معمولی تعریف یک تابع، شما نیازی به این کلمهٔ کلیدی ندارید، اما در توابع بی‌نام برای اینکه‌ پارامتر‌ها از هم جدا شوند، استفاده از این کلمهٔ کلیدی الزامی و لازم است. 

اگر بخواهیم یک مثال بزنیم تا برایتان شفاف‌تر شود، فرض کنید می‌خواهیم نام و نام خانوادگی شخصی را گرفته، کمی آن را استایل‌دهی کنیم و سپس به آن را به تابع برگردانیم! برای این منظور، به این شکل عمل خواهیم کرد؛ یک تابع معمولی همان‌طور که در جلسهٔ قبل گفته شده، به این صورت تعریف می‌شود؛ 

func getFullName(_ first_name: String, _ last_name: String) -> String {
  
   let _full_name = "First Name is : \(first_name) and Last Name is : \(last_name)" 

   return _full_name
}

print(getFullName("Mohammad", "Abasi")) // First Name is : Mohammad and Last Name is : Abasi

اما این داستان در توابع بی‌نام کمی فرق می‌کند و تعریف آن به این صورت است؛ 

let _full_name = { (_ first_name: String, _ last_name: String) -> String
 in 
    let _full_name =  "First Name is : \(first_name) and Last name is : \(last_name)"
    
    return _full_name 
}

print(_full_name("Mohammad", "Abasi"))

ملاحضه می‌کنید که ما دو پارامتر از نوع رشته با نام‌های first_name و last_name تعریف کرده و نوع برگشتی آن را هم String ( رشته‌ ) قرار داده‌ایم، فراموش نکنید که حتما باید از کلمهٔ کلیدی in بعد از مشخص کردن نوع دادهٔ برگشتی استفاده کنید؛ در غیر اینصورت، با این خطا مواجه خواهید شد؛ 

main.swift:1:20: error: expected ',' separator
var closuer = { (_ first_name: String, _ last_name: String) -> String 
                   ^
                  ,
main.swift:3:42: error: use of unresolved identifier 'first_name'
    let _full_name =  "First Name is : \(first_name) and Last name is : \(last_name)"
                                         ^~~~~~~~~~
main.swift:3:75: error: use of unresolved identifier 'last_name'
    let _full_name =  "First Name is : \(first_name) and Last name is : \(last_name)"
                                                                          ^~~~~~~~~
main.swift:1:15: error: unable to infer complex closure return type; add explicit type to disambiguate
var closuer = { (_ first_name: String, _ last_name: String) -> String 
              ^

پس آن ( in ) را فراموش نکنید. در بدنهٔ تابع، ما یک ثابت ( let ) تعریف کرده و سپس یک رشته کامل همراه با پارامتر‌ها به آن انتساب می‌دهیم و در آخر آن را به تابع برگشت ( return ) می‌دهیم. علاوه بر این‌که شما می‌توانید به این صورت عمل کنید ( انتساب تابع به متغییر ) می‌توانید بدون متغییر این‌کار را هم بکنید!  فرض کنید می‌خواهیم دو عدد را با هم جمع بزنیم و فقط می‌خواهیم یک‌بار برایمان این‌کار انجام شود. برای این منظور به این صورت می‌توانیم عمل کنیم؛ 

let _addition = { (_ number_one: Double, _ number_two: Double) -> Double in
    return number_one + number_two
}(10,20)

print(_addition) // Result is = 30 

یا 

print({ (_ number_one: Double, _ number_two: Double) -> Double in
    return number_one + number_two
}(10,20)) // Result is = 30 

همان‌طور که مشاهده می‌کنید، در دو حالت یکی هستند، تنها تفاوتی که وجود دارد، بعد از آخرین آکولاد ( { ) است. یعنی این قسمت؛ 

{(10,20)) // Result is = 30 

شما در این قسمت و در بین دو پرانتز () به پارامتر‌هایی که تعیین کرده‌اید، آرگومان‌های خودتان را ارسال می‌کنید ( در این مثال؛ ۱۰ و ۲۰ ) و در نتیجه، به جای این‌که یک تابع برگشت داده شود، یک نتیجه را به دنبال خواهد داشت. اگر این‌کار را نکنید و با تابع  print بخواهید ببینید که بدون آرگومان دادن، چه اتفاقی خواهد افتاد، نتیجه در خروجی یا تابع خواهد بود؛ 

print({ (_ number_one: Double, _ number_two: Double) -> Double in
    
    return number_one + number_two
}) // Result is = (Function)

اگر قصد شما این است که نتیجه را در همان زمان مورد استفاده قرار دهید، استفاده از دو روش بالا، جوابگوی شماست و اگر خواستید یک تابع داشته باشید که یک کار مشخص را انجام داده و بعد از آن دیگر مورد استفاده قرار نگیرد، می‌توانید از حالت اول استفاده کنید. 

مرتب سازی عناصر با توابع بی‌نام ( Sort Elements in Closures ) 

شما می‌توانید عناصر یک آرایه را با استفاده از توابع بی‌نام، مرتب‌ کنید! در این نوع مرتب‌سازی بستگی به شما دارد که چگونه بخواهید عمل مرتب‌سازی را انجام دهید. بگذارید مثالی را ارائه دهیم تا موضوع را بیشتر و بهتر درک کنید و سپس به سراغ توضیحات تکمیلی خواهیم رفت؛ 

let _numbers = [1,3,2,4,6,5] 

var sorted_numbers = _numbers.sorted(by: { (_ number_one: Int, _ number_two: Int) -> Bool in
    
    return number_one < number_two
})

print(sorted_numbers)

همان‌طور که در قطعه کد بالا مشاهده می‌کنید، ابتدا یک آرایه تعریف کرده‌ایم ( [let _numbers = [1,3,2,4,6,5 ) و سپس یک متغییر دیگر با نام ( sorted_numbers ) تعریف کرده‌ که خود یک آرایه است! به این دلیل می‌گویم آرایه، که متد sotred یک آرایه را برمی‌گرداند. کار این متد مرتب‌سازی یک آرایه براساس آرگومانیست که شما به آن می‌دهید. این متد از کلاس آرایه است ( numbers.sorted_ ). بیاید به تشریح آرگومانی که دریافت می‌کنید، بپردازیم. البته ملاحظه می‌کنید که آرگومان، یک تابع بی‌نام است! شما می‌توانید با برچسب :by تابع بی‌نام خود را تعریف کرده و سپس متد sorted کار خود را شروع می‌کند و به مرتب‌سازی اعضای آرایه می‌پردازد. شما در تابع بی‌نامی که تعریف می‌کنید باید دو پارامتر را در نظر بگیرید. واضح است که دو پارامتر برای اعضای آرایه است که قرار است در بدنهٔ تابع مورد بررسی قرار گیرند و نتیجهٔ نهایی  به تابع sorted داده شود. ما دو پارامتر به نام‌های ( number_one, number_two‌ ) تعریف کرده‌ایم که هر دو از نوع عددی هستند ( با توجه به نوع دادهٔ آرایه خود باید پارامتر‌ها را مشخص کنید ) و سپس نوع برگشتی را Bool انتخاب کردیم که نتیجهٔ true یا false را برمی‌گرداند. و در نهایت کلمهٔ کلید in که برای توابع بی‌نام همان‌طور که گفته‌ بودیم، لازم و اجباریست. در بدنهٔ تابع، چیزی جز یک دستور نخواهیم داشت! با استفاده از دستور return number_one < number_two می‌گویم اگر عدد اوله ( عضو اول آرایه ) از عدد دوم (‌ عضو دوم آرایه ) کوچک‌تر بود، نتیجه true ( درست ) را برگردان و در غیر این‌صورت false ( نادرست ) را برگردان. از آنجایی که عدد اول یعنی ۱، کوچک‌تر از عدد دوم یا همان عضو ۳ است، بنا‌براین true یا همان درست به تابع برگشت داده می‌شود که در نتیجه عدد ۱ از آرایه، در جای خود باقی می‌ماند. اما در تکرار بعدی، عدد اول یعنی ۳ کوچک‌تر از عدد ۲ نیست و نتیجهٔ false یا نادرست برگشت داده خواهد شد که در نهایت عدد ۲ در جایگاه عدد ۳ قرار می‌گیرد و الی آخر... .

این هم یک نمونه از کاربرد توابع بی‌نام بود که با متد sorted از کلاس آرایه همکاری کرد تا به مرتب‌سازی یک آرایه بپردازد. شما همچنین می‌توانید از خلاقیت خود استفاده کنید و کد‌نویسی زیباتر و خلاقانه‌تری انجام دهید. شروع کنید و لذت ببرید!

نوع‌های شمارشی ( Enumerations ) چیستند؟ 

نوع‌های شمارشی یک نوع داده‌ایست که شامل گروهی از داده‌ها مرتبط با هم هستند! در مقابل هم باعث خوانایی بیشتر پروژهٔ نرم‌افزاری خواهد شد. بگذارید باز هم با یک مثال شروع کنیم تا در توضیحات برای شما عزیزان، شفاف‌تر و قابل‌ درک‌تر شود. برای تعریف یک enum می‌بایست از Syntax زیر استفاده کنیم؛ 

enum EnumName {
    
    // Enumeration values are described here 
}

همان‌طور که مشاهده می‌کنید، حالت کلی تعریف آن به این صورت است. ابتدا کلمهٔ کلید enum را آورده که مشخص کنندهٔ تعریف یک نوع شمارشی است و سپس باید یک نام هم برای آن در نظر بگیرید ( حتما نامی را انتخاب کنید که بیان‌گر کاری است که انجام می‌دهد )‌ و در نهایت در بین دو آکولاد {} می‌توانید داده‌های خود که مرتبط با نام است تعریف کنید! به این مثال به دقت نگاه کنید؛‌

enum ProgrammingLanguages {
    
    case C
    case Java
    case Rust
    case R
    case Python 
    case PHP 
    case Javascript
    case HTML
    case Perl
    case Ruby
    case Swift

}

var language = ProgrammingLanguages.C

print("\(Language) is programming language!") // C is programming language!

در قطعه کد بالا همان‌طور که ملاحضه کردید، ما یک نوع شمارشی به نام ProgrammingLanguages تعریف کرده‌ایم که به معنی‌ زبان‌های برنامه‌نویسی است و درواقع داده‌های آن هم مرتبط با برنامه‌نویسی هستند نه چیزی دیگر! به عنوان مثال ( C,Java,Rust و ... ) همهٔ آن‌ها مرتبط با برنامه‌نویسی هستند و به خاطر همین است که ما به آن‌ها می‌گویم گروهی از داد‌ه‌ها که با هم مرتبط هستند! اگر یادتان باشد، گفته بودیم که نوع‌های شمارشی در پروژهٔ شما می‌تواند خوانایی بالایی ایجاد کند. اگر مثال بالا را بخواهیم با آرایه‌ها بنویسیم، به این صورت خواهد بود؛ 

var programming_languages = ["C", "C++", "Java", "Rust", "R", "Javascript", "PHP", "Swift", "Ruby", "Perl", "Python", "HTML"]

آیا با این روش می‌توانید سریع به دادهٔ مورد‌نظر خود دسترسی داشته باشید؟‌ مسلما خیر! چرا که به این صورت اگر بخواهید داد‌ه‌های خود را تعریف کنید و از آن‌ها استفاده کنید، وقت و انرژی زیادی از شما خواهد گرفت! پیدا کردن ایندکس ( به عنوان مثال R ) وقت و انرژی از شما خواهد گرفت. اما اگر با نوع‌های شمارشی بنویسید، علاوه بر کد‌نویسی زیبا‌تر و تمیز‌تر، دسترسی سریع‌تر و راحت‌تری هم خواهید داشت. به این مثال دقت کنید؛ 

enum Languages {
    
    case C
    case Java
    case Rust
    case R
    case Python 
    case PHP 
    case Javascript
    case HTML
    case Perl
    case Ruby
    case Swift
}

var language = Languages.Javascript


switch language {
    case .C:
    print("C is programming language!")
    case .Java:
    print("Java is programming language!")
    case .Rust:
    print("Rust is programming language!")
    case .R:
    print("R is programming language!")
    case .Python:
    print("Python is programming language!")
    case .PHP:
    print("PHP is programming language!")
    case .Javascript:
    print("Javascript is programming language!") // Javascript is programming language!
    case .HTML:
    print("HTML is programming language!")
    case .Perl:
    print("Perl is programming language!")
    case .Ruby: 
    print("Ruby is programming language!")
    case .Swift:
    print("Ruby is programming language!")

}

در مثال بالا مشاهده می‌کنید که شما می‌توانید به راحتی با تعریف یک نوع شمارشی، به راحتی هرچه‌ تمام‌تر به داده‌های آن با استفاده از نام آن‌ها دسترسی داشته باشید. در دستورات شرطی مثل switch دقت کنید که ابتدا باید مقدار دادهٔ مورد نظرتان از نوع شمارشی که تعریف کرده‌اید را به متغییر انتساب داده و سپس به عنوان یک مقدار به دستور switch بدهید تا بتواند آن را بررسی کند! چرا که در switch مقدار باید ثابت باشد نه متغییر! و سپس در بدنهٔ شرط، با استفاده از دات ( . ) و نام دادهٔ مورد‌نظر در caseها ( case .HTML ) می‌توانید داده‌‌ی ثابتی که در switch تعریف کردید را با مقادیر caseها مقایسه کنید و در نهایت خروجی متناسب با آن را مشاهده کنید. 

 

امیدواریم که این جلسه مورد رضایت شما قرار گرفته باشد. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

آموزش زبان برنامه‌نویسی سوئیفت - جلسه  آخر 

مواردی که در این جلسه یاد خواهید گرفت: کلاس‌ها و ساختار‌ها

در این جلسه که جلسه‌ی آخر است، ما به بررسی مبحث کلاس‌ها و ساختار داده خواهیم پرداخت. اول از همه بگذارید تا تعریفی از کلاس و ساختار داده داشته باشیم و سپس به بقیه‌ی موارد خواهیم پرداخت. 

کلاس‌ها ( Classes ) چیستند؟ 

یک کلاس واقعی را در نظر بگیرید که از تعدادی زیاد یا کمی دانش‌آموزان تشکیل شده است. نام کلاس به عنوان مثال می‌تواند کلاس کامپیوتر-۲ باشد! و معلم و دانش‌آموزان هم اعضای آن کلاس هستند. معلم یک وظیفه دارد و دانش‌آموزان هم وظیفه‌ای دیگر...، در دنیای برنامه‌نویسی هم ما کلاس‌ها را داریم که در پروژه‌مان به کمک ما می‌آیند. کلاس‌ها، متشکل ویژگی‌ها ( Properties ) و متد‌ها ( Methods ) هستند که می‌توانند به صورت اختیاری به کلاس‌ها اضافه شوند. در سوئیفت شما می‌توانید بدون هیچ رابط یا فایلی، کلاس‌های خودتان را در یک فایل واحد تعریف کنید. 

نکته

یک نمونه از یک کلاس، به طور معمول به عنوان یک شئ ( Object ) شناخته می‌شود؛ اما کلاس‌ها و ساختار به دلیل این‌که از نظر عملکرد با سایر زبان‌های برنامه‌نویسی، مثل هم هستند، از اصطلاح عمومی‌تر آن، یعنی نمونه استفاده می‌شود. 

ساختار داده ( Structure ) چیستند؟ 

ساختار داده هم دقیقا مانند کلاس‌ها هستند؛ که ثوابت، متغییرها و توابع را در خود ذخیره می‌کنند. 

تعریف کلاس‌ و ساختار 

نحوه‌ی تعریف کلاس و ساختار در سوئیفت، مشابه هم است! به این مثال دقت کنید؛ 

class Languages {
    
    // Class definition goes here 
}

struct DataTypes {
    
    // Structure dfinition goes here
}

همان‌طور که مشاهده کردید، ما با استفاده از کلمه‌ی کلید class یک کلاس به نام Languages تعریف کرده و سپس با دو براکت {} باز و بسته، می‌توانیم کُد‌های خودمان را بنویسیم. در مقابل می‌بینید که تعریف ساختار داده، مشابه کلاس است! ابتدا کلمه‌ی کلید  struct را نوشته و سپس یک نام برای آن انتخاب می‌کنیم. قوائد نام‌گذاری در کلاس‌ها و ساختار داده، به صورت پاسکال کِیس ( PascalCase ) هستش. یعنی حرف اول هر کلمه می‌بایست بزرگ نوشته شود و مابقی کلمه به حروف کوچک. مانند؛  ProgrammingLanguages. 

با یک مثال بهتر و شفاف‌تر، این موضوع را برای شما قابل‌ درک‌تر خواهیم کرد؛ 

class FullName {
    
    var first_name : String?
    var last_name : String?
    
    // Set function 
    func setFullName(_ first_name : String, _ last_name : String ) {
        
        self.first_name = first_name
        self.last_name = last_name 
    }
    
    // Get function 
    func getFullName() ->  String {
        
        return "First name is : \(self.first_name!)\n" + "Last name : \(self.last_name!)"
    }
}

struct DataTypes {
    
    let _age : Int 
    let _name : String 
    let _average : Double 
}

let _full_name = FullName()
let _datatype = DataTypes(_age: 20,_name: "Mohammad",_average: 20.0)
_full_name.setFullName("Mohammad", "Abasi")
print(_full_name.getFullName())
print("Age is : \(_datatype._age)")
print("First name is : \(_datatype._name)")
print("Average is : \(_datatype._average)")

هما‌ن‌طور که مشاهده می‌کنید، یک کلاس با نام FullName تعریف شده و یک کلاس هم با نام DataTypes. در کلاس FullName ما دو متغییر و دو تابع داریم و در طرف دیگر ما ساختار داده‌ی DataTypes را خواهیم داشت که دارای سه متغیر می‌باشد ( age_, _name,_average ) که برای ذخیره‌ی داده‌های مرتبط استفاده می‌شوند. در ادامه ما دو شئ از کلاس FullName و DataTypes ساخته‌ایم که در ادامه از ویژگی‌ها و همچنین متُد‌های آن استفاده کرده‌ایم ( به خطوط ۱۹ تا ۲۳ دقت کنید ). 

نکته

متُد، همانند تابعی است که مجموعه‌ای از کد‌ها را هنگامی که فراخوانی شده باشد، اجرا می‌کند و به این خاطر به تابع تفاوت دارد که تابع به صورت مجزا نوشته می‌شود و متُد در داخل کلاس تعریف می‌شود.

همچنین شما می‌توانید نوع ساختار داده‌ای را که تعریف کردید، را در کلاس به کار ببرید! به این مثال توجه کنید؛ 


class FullName {
    
    var first_name : String?
    var last_name : String?
    var data_types = DataTypes()
    
    // Set function 
    func setFullName(_ first_name : String, _ last_name : String ) {
        
        self.first_name = first_name
        self.last_name = last_name 
    }
    
    // Get function 
    func getFullName() ->  String {
        
        return "First name is : \(self.first_name!)\n" + "Last name : \(self.last_name!)"
    }
}
struct DataTypes {
    
    var age : Int = 0
    var name : String = ""
    var average : Double = 0
}

let _full_name = FullName()
var _datatype = DataTypes()
_datatype.age = 20
_datatype.name = "Mehdi"
_datatype.average = 17.15
_full_name.setFullName("Mohammad", "Abasi")
print(_full_name.getFullName())
print("Age is : \(_datatype.age)")
print("First name is : \(_datatype.name)")
print("Average is : \(_datatype.average)")
_full_name.data_types.age = 20
_full_name.data_types.name = "Mohammad"
_full_name.data_types.average = 20.0
print("Name is  : \(_full_name.data_types.name)\nAnd Age is : \(_full_name.data_types.age)\nAnd Average is : \(_full_name.data_types.average)")

ما از همان ساختار قبلی ( DataTypes ) استفاده کردیم و برای این‌که بتوانیم از آن در کلاسمان استفاده کنیم، لازم است مقداردهی را در ساختار داده ( به خطوط ۱۳ تا ۱۷ دقت کنید ) انجام دهید یا این‌که در خود کلاس و هنگامی که متغییر از نوع ساختار داده تعریف می‌کنید ( data_types ) در سازنده‌ی آن بین دو پرانتز ()، مقادیر را وارد کنید، همانند زیر؛ 


class FullName {
    
    var first_name : String?
    var last_name : String?
    var data_types = DataTypes(age : 0, name : "", average : 0)
    
    // Set function 
    func setFullName(_ first_name : String, _ last_name : String ) {
        
        self.first_name = first_name
        self.last_name = last_name 
    }
    
    // Get function 
    func getFullName() ->  String {
        
        return "First name is : \(self.first_name!)\n" + "Last name : \(self.last_name!)"
    }
}
struct DataTypes {
    
    var age : Int
    var name : String
    var average : Double
}

let _full_name = FullName()
var _datatype = DataTypes(age : 20, name : "Mohammad", average : 20)
_datatype.age = 20
_datatype.name = "Mehdi"
_datatype.average = 17.15
_full_name.setFullName("Mohammad", "Abasi")
print(_full_name.getFullName())
print("Age is : \(_datatype.age)")
print("First name is : \(_datatype.name)")
print("Average is : \(_datatype.average)")
_full_name.data_types.age = 20
_full_name.data_types.name = "Mohammad"
_full_name.data_types.average = 20.0
print("Name is  : \(_full_name.data_types.name)\nAnd Age is : \(_full_name.data_types.age)\nAnd Average is : \(_full_name.data_types.average)")

پس باید حتما در ساختار‌های داده، مقدار‌دهی را هم انجام دهید، فرقی نمی‌کند که شما ساختار داده‌یتان را به صورت مجزا تعریف می‌کنید یا برای استفاده در کلاس! در هر صورت، باید مقدار‌دهی را انجام دهید و این الزام است! یادتان باشد که اگر مقداردهی را در سازنده‌ی ( Constructor ) ساختار داده، انجام داده باشید و بخواهید که به صورت مستقیم و بدون دخالت در تغییر نوع‌های داده‌ی آن، از آن استفاده کنید، می‌توانید کلمه‌ی کلید let را برای ساختار داده‌ی خود به کار ببرید ( ()let _data_datatype = DataTypes ) و اما اگر نه، بخواهید در ادامه‌ی پروژه‌یتان، مقادیر ویژگی‌های آن را تغییر دهید، باید از کلمه‌ی کلید var استفاده کنید! نه تنها در تعریف یک شئ ساختار داده، بلکه برای تغییر ویژگی‌های آن هم باید از همین کلمه‌ی کلید استفاده کنید تا مجوز تغییر داده‌ها را داشته باشید. پس به این نکته هم دقت داشته باشید

هنگامی که شما یک نمونه از کلاس یا ساختار داده ایجاد می‌کنید، می‌توانید در سازنده‌ی آن، ویژگی‌ها کلاس یا ساختار داده را مقدار‌دهی کنید، به این شکل؛ 

struct Website {
    
    var name : String 
    var subject : String 
}
class Project {
    
    var version : Float? 
    var name : String?
    
    init (version : Float,  name : String) {
        
        self.version = version
        self.name = name
    }
}

var website = Website(name : "iostream.ir", subject : "Programming and Graphic Business and .... ")

var project =  Project(version : 2.1, name : "Fanoox")


print(website.name)
print(website.subject)
print()
print(project.version!)
print(project.name!)

دقت کنید که سازنده با کلمه‌ی کلید func‌ همراه نمی‌شود! بلکه از طریق کلمه‌ی کلید init ‌باید سازنده را تعریف و به آن پارامتر داد. همانند مثال بالا که مشاهده می‌کنید. در هنگامی که از دو ویژگی version و name استفاده می‌کنید، باید با علامت تعچب ( ! ) آن را از حالت Wrap به Unwrap کنید! یا به اصطلاح آن را از حالت بسته‌بندی شده، خارج کنید. 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

به گفتگو ملحق شوید

شما همین الآن می‌توانید مطلبی را ارسال و بعداً ثبت‌نام کنید. اگر حساب کاربری دارید، و با حساب کاربری خود مطلب ارسال کنید.
نکته: مطلب شما قبل از انتشار نیاز به بازبینی توسط میانجی‌گر‌ها دارد.

مهمان
ارسال پاسخ به این موضوع ...

×   شما در حال چسباندن محتوایی با قالب بندی هستید.   حذف قالب بندی

  تنها استفاده از ۷۵ اموجی مجاز می باشد.

×   لینک شما به صورت اتوماتیک جای گذاری شد.   نمایش به عنوان یک لینک به جای

×   محتوای قبلی شما بازگردانی شد.   پاک کردن محتوای ویرایشگر

×   شما مستقیما نمی توانید تصویر خود را قرار دهید. یا آن را اینجا بارگذاری کنید یا از یک URL قرار دهید.


  • کاربران آنلاین در این صفحه   0 کاربر

    هیچ کاربر عضوی،در حال مشاهده این صفحه نیست.

×
×
  • جدید...