معرفی زبان برنامه نویسی سوئیفت – Swift
معرفی زبان برنامه نویسی سوئیفت – Swift
سوئیفت یک زبان برنامه نویسی کامپایلری چند شیوه ای عمومی است که برای iOS، macOS، watchOS، tvOS و لینوکس توشر شرکت Apple تولید شده است. سوئیفت یک زبان برنامه نویسی کامپایلری چند شیوه ای عمومی است که برای iOS، macOS، watchOS، tvOS و لینوکس توشر شرکت Apple تولید شده. زبان برنامه نویسی سوئیفت به گونه ای طراحی شده است که با فریم ورک های Cocoa و Cocoa Touch و مجموعه بزرگی از کدهای Objective-C که برای محصولات اپل نوشته شده است، کار می کند. زبان برنامه نویسی سوئیت در برابر کدهای اشتباه انعطاف پذیرتر از Objective C و همچنین کوتاه تر است. این زبان با فریم ورک کامپایلر LLVM موجود در Xcode 6 و بالاتر و روی پلتفرم هایی غیر از لینوکس ساخته شده است و از کتابخانه Objective C استفاده می کند که به کدهای C، Objective C، C++ و سوئیفت اجازه می دهد در داخل یک برنامه همزمان اجرا شوند.
محصولات آموزشی مرتبط با این مقاله :
– صفر تا صد آموزش سوئیفت و برنامه نویسی اپل
– محصولات آموزشی مرتبط با برنامه نویسی
زبان برنامه نویسی سوئیفت ( swift )از مفاهیم پایه ای که باعث انعطاف پذیر شدن Objective C شده است پشتیبانی می کند، از جمله Dynamic Dispatch، late binding گسترده، برنامه نویسی توسعه پذیر و ویژگی های مشابه. همچنین این ویژگی ها دارای تعادل شناخته شده ای بین عملکرد و امنیت هستند که سوئیفت برای رفع آن طراحی شده است. برای امنیت، سوئیفت سیستمی را معرفی کرده است که خطاهای رایج برنامه نویسی مانند اشاره گرهای خالی را رفع می کند و قابلیت شکر نحوی یا Synthetic Sugar را معرفی کرده است تا از مشکل Pyramid of Doom جلوگیری شود. به خاطر مشکلات عملکرد، شرکت اپل تلاش زیادی در بهینه سازی انجام داده است که فراخوانی متدها و دسترسی ها را از بین می برد تا از این سر بار جلوگیری کند. اساسا سوئیفت مفهوم توسعه پذیری پروتکل را افزوده است که یک سیستم توسعه پذیری است که می تواند روی Type ها، ساختارها و کلاس ها اعمال شود. شرکت اپل این قابلیت را یک تغییر واقعی در الگوهای برنامه نویسی معرفی کرده است که به آن “برنامه نویسی پروتکل محور” می گویند.
زبان برنامه نویسی سوئیفت در کنفرانس جهانی توسعه دهندگان (WWDC) 2014 معرفی شد. در طی سال 2014 به ورژن 1.2 به روزرسانی شد و در WWDC 2015 با یک به روز رسانی بزرگ به سوئیفت 2 ارتقا پیدا کرد. این زبان در ابتدا یک زبان برنامه نویسی اختصاصی بود، اما ورژن 2.2 یک نرم افزار کد باز شد و در سوم دسامبر سال 2015 تحت لیسانس Apache 2.0 برای پلتفرم های Apple و Linux عرضه شد. شرکت IBM وبسایت شبیه ساز سوئیفت خود را معرفی نمود که به توسعه دهندگان اجازه می دهد کد را در یک پنل نوشته و خروجی را در یک پنل دیگر نمایش می دهد.
یک نسخه رایگان دیگر از زبان برنامه نویسی سوئیفت به عنوان بخشی از کامپایلر Elements از شرکت RemObjects Software وجود دارد که پلتفرم های Cocoa، زیرساخت زبان مشترک .NET، جاوا و اندروید را هدف قرار داده است. از آنجایی که این زبان کد باز است، قسمت هایی از آن به وب انتقال یافته است. تاکنون تعدادی فریم ورک های وب مانند Kitura، Perfect و Vapor توسعه یافته اند. همچنین یک کارگروه رسمی برای APIهای سرور توسط شرکت Apple راه اندازی شده است که اعضای انجمن توسعه دهندگان سوئیفت نقش مرکزی را در آن ایفا می کنند.
تاریخچه
توسعه زبان برنامه نویسی سوئیفت در جولای سال 2010 توسط کریس لتنر آغاز شد که در نهایت بسیاری از دیگر برنامه نویس های Apple در آن همکاری کردند. زبان برنامه نویسی سوئیفت ایده های خود را از زبان های Objective C، Rust، Haskell، Ruby، Python، C#، CLU و بسیاری از زبان های دیگر گرفت. در دوم ژوئن سال 2014، برنامه کنفرانس جهانی توسعه دهندگان اپل اولین برنامه عرضه شده به صورت عمومی بود که با زبان برنامه نویسی سوئیفت نوشته شده بود. یک ورژن Beta از زبان برنامه نویسی سوئیفت برای توسعه دهندگان Apple در آن کنفرانس عرضه شد، اما شرکت اپل قول نداد که کد منبع ورژن نهایی سوئیفت با ورژن آزمایشی سازگاری داشته باشد. شرکت Apple برنامه ریزی کرد تا در صورت نیاز مبدل های کد منبعی را برای عرضه نسخه کامل بسازد.
یک دستورالعمل 500 صفحه ای به نام “زبان برنامه نویسی سوئیفت” نیز در این کنفرانس عرضه شد که در فروشگاه iBooks و وبسایت رسمی موجود است. نسخه 1.0 سوئیفت در نهم سپتامبر سال 2014 به همراه Xcode 6.0 Gold Master برای iOS عرضه شد. سوئیفت 1.1 در 22 اکتبر سال 2014 به همراه Xcode 6.1 عرضه شد. سوئیفت 1.2 در 8 آوریل سال 2015 به همراه Xcode 6.3 عرضه شد. سوئیفت 2.0 در کنفرانس WWDC سال 2015 معرفی شد و در 21 سپتامبر سال 2015 برای انتشار برنامه ها در فروشگاه App Store قرار گرفت. سوئیفت 3.0 در 13 سپتامبر سال 2016 عرضه شد.
زبان برنامه نویسی سوئیفت در نظرسنجی توسعه دهندگان وبسایت Stack Overflow در سال 2015، رتبه اول محبوب ترین زبان برنامه نویسی را کسب کرد و در سال 2016 رتبه دوم را به خود اختصاص داد.
در طی کنفرانس WWDC سال 2016، شرکت اپل یک برنامه مخصوص iPad به نام Swift Playgrounds را معرفی کرد که هدف آن آموزش کدنویسی در سوئیفت به افراد است. این برنامه یک محیط سه بعدی مانند بازی های ویدئویی دارد که وقتی کدها به ترتیب خاصی نوشته و اجرا می شوند، بازخورد می دهد.
در ژانویه سال 2017، کریس لتنر جدا شدن خود از شرکت Apple را اعلام کرد تا مقام جدیدی را در شرکت Tesla Motors بپذیرد و رهبری پروژه سوئیفت بر عهده Ted Kremenek قرار گرفت.
ویژگی ها
زبان برنامه نویسی سوئیفت جایگزینی برای Objective C است که از مفاهیم نظریه زبان برنامه نویسی مدرن استفاده می کند و سعی دارد یک قاعده ساده تر ارائه کند. سوئیفت در هنگام معرفی شدن به عنوان “Objective C بدون C” معرفی شد.
زبان برنامه نویسی سوئیفت به طور پیش فرض اشاره گرها و دیگر دسترسی های ناامن را افشا نمی کند، برخلاف Objective C که به طور گسترده ای از اشاره گرها برای اشاره به نمونه های اشیا استفاده می کند. همچنین استفاده Objective C از یک قاعده شبیه Smalltalk برای فراخوانی متدها با یک سبک Dot-Notation و سیستم Namespace جایگزین شده است که بیشتر برای برنامه نویس های دیگر زبان های رایج شیء محور مانند جاوا یا C# آشنا است. زبان برنامه نویسی سوئیفت پارامترهای نامگذاری شده حقیقی را معرفی کرده است و مفاهیم کلیدی Objective C از جمله پروتکل ها، Closure ها، و دسته بندی ها را حفظ کرده است و اغلب قواعد پیشین را با نسخه های تمیزتر جایگزین کرده است و اجازه می دهد این مفاهیم روی دیگر ساختارهای زبانی اعمال شوند، مانند Type های شمارشی (enums).
Typeها، متغیرها و هدف گذاری
در محیط های Cocoa و Cocoa Touch، بسیاری از کلاس های رایج بخشی از کتابخانه Foundation Kit بودند. اینها شامل کتابخانه رشته NSString (با استفاده از یونیکد) و کلاس های مجموعه NSArray و NSDictionary بودند. زبان Objective C تکه های مختلفی از Synthetic Sugar عرضه می کرد تا اجازه دهد برخی از این اشیا به صورت لحظه ای در زبان ساخته شوند، اما وقتی ساخته شدند، اشیا با فراخوانی شیء دستکاری می شدند. برای مثال، الحاق کردن دو عدد NSStrings نیازمند فراخوانی های متدی مانند زیر بود:
NSString *str = @"hello,"; str = [str stringByAppendingString:@" world"];
در زبان برنامه نویسی سوئیفت بسیاری از این Type های اساسی به هسته زبان اضافه شده اند و می توان آنها را مستقیما دستکاری کرد. برای مثال، رشته ها به صورت نامرئی به NSString متصل شده اند و اکنون می توان با عملگرد + آنها را الحاق کرد که این امر باعث می شود قاعده نحوی بسیار ساده تر شود. مثال قبلی به شکل زیر نوشته می شود:
var str = "hello," str += " world"
زبان برنامه نویسی سوئیت از پنج سطح کنترل دسترسی برای علائم پشتیبانی می کند: open ، public ، internal ، fileprivate و private . برخلاف بسیاری از زبان های شیء گرا، این کنترل های دسترسی سلسله مراتب وراثت را نادیده می گیرند. Private نشان می دهد که یک نشانه تنها از طریق محدوده کنونی قابل دسترسی است، fileprivate نشان می دهد که تنها از داخل فایل قابل دسترسی است، internal نشان می دهد که از داخل ماژول قابل دسترسی است، public نشان می دهد که از هر ماژولی قابل دسترسی است و open (تنها برای کلاس ها و متدهای آنها) نشان می دهد که ممکن است کلاس در خارج از ماژول به زیرکلاس تبدیل شده باشد.
اختیاری ها و زنجیره
یک ویژگی جدید مهم در زبان برنامه نویسی سوئیفت، option typeها هستند که به رفرنس ها و مقادیر اجازه می دهند مانند الگوهای رایج در C عمل کنند که یک اشاره گر ممکن است به یک مقدار اشاره داشته باشد یا خالی باشد. این نشان می دهد که typeهای غیر اختیاری نمی توانند با خطای اشاره گر خالی مواجه شوند، زیرا کامپایلر این امر را غیرممکن می سازد.
نوع های اختیاری با مکانیزم optional ساخته می شوند. برای ساخت یک Integer که قابلیت Null بودن دارد، باید از اعلانی مانند var optionalInteger: Optional<Int> استفاده شود. سوئیفت هم مانند C# برای این کار دارای syntactic sugar است و اجازه می دهد با قرار دادن یک علامت سوال بعد از نامِ Type، مشخص کنیم که یک متغیر اختیاری است، مانند var optionalInteger: Int? . متغیرها یا ثابت هایی که به عنوان اختیاری مشخص شده اند یا یک مقدار از نوعِ مربوطه دارند یا nil هستند. Typeهای اختیاری بر روی Type اصلی قرار می گیرند و یه نمونه متفاوت ایجاد می کنند. String و String? اصولا دو نوع متفاوت هستند و دومی با int? وجه مشابه بیشتری نسبت به string دارد.
برای دسترسی به مقدار داخل با فرض اینکه Nil نیست، باید unwrap یا باز شود تا نمونه داخلی نمایان شود. این کار با عملگر ! صورت می گیرد:
let myValue = anOptionalInstance?.someMethod()
در این مورد، عملگر i عبارت anOptionalInstance را unwrap می کند تا نمونه داخلی را نشان دهد تا فراخوانی متد در آن انجام شود. اگر anOptionalInstance خالی یا nil باشد، خطای null-pointer صورت می گیرد. این موضوع در عمل می تواند آزاردهنده باشد، بنابراین سوئیفت همچنین قابلیت optional chaining را دارد تا بررسی کند که نمونه nil است و اگر غیر null باشد، آن را unwrap کند:
let myValue = anOptionalInstance?.someMethod()
در این مورد اگر anOptionalInstance خالی یا nil نباشد، runtime تنها someMethod را فراخوانی می کند و خطا را سرکوب می کند. معمولا این کار نیازمند این است که برنامه نویس قبل از ادامه دادن بررسی کند که myValue خالی یا nil نباشد. مبدا اصطلاح chaining از مورد رایج تری گرفته شده است که چندین فراخوانی متد به هم زنجیر شده اند. برای مثال:
let aTenant = aBuilding.TenantList[5] let theirLease = aTenant.leaseDetails let leaseStart = theirLease?.startDate
می تواند با کد زیر جایگزین شود:
let leaseStart = aBuilding.TenantList[5].leaseDetails?.startDate
علامت ? باعث جلوگیری از pyramid of doom می شود.
در زبان برنامه نویسی سوئیفت 2 کلمه کلیدی جدید guard برای مواردی معرفی شده است که اگر شرطی برآورده نشده است، اجرای کد باید متوقف شود:
guard let leaseStart = aBuilding.TenantList[5]?.leaseDetails?.startDate else { //handle the error case where anything in the chain is nil //else scope must exit the current method or loop } //continue on, knowing that leaseStart is not nil
استفاده از guard سه مزیت دارد. با اینکه قاعده نحوی می تواند به عنوان یک عبارت if عمل کند، مزیت اصلی آن استنتاج کردن عدم خالی یا null بودن است. یک عبارت if نیازمند یک موضوع است، درحالیکه عبارت guard موضوع را براساس شرط ارائه شده حدس می زند. همچنین به علت اینکه guard به استثنای else ، دارای Scope نیست، leaseStart به عنوان یک اختیاری Unwrap شده برای دامنه بالای guard ارائه شده است. در نهایت اگر تست عبارت guard با شکست مواجه شود، سوئیفت نیازمند این است که else از متد یا حلقه کنونی خارج شود تا مطمئن شود در هنگام nil بودن، به leaseStart دسترسی وجود ندارد. این کار با کلمات کلیدی return ، continue یا break صورت می گیرد.
Objective C ضعیف بود و اجازه میداد هر متدی در هر شی ای و در هر زمانی فراخوانی شود. اگر فراخوانی متد شکست می خورد، یک handler پیش فرض در runtime وجود داشت که نتیجه nil ارائه میداد. این بدین معنی بود که نیازی به unwrap کردن یا تست کردن نبود که عبارت هم ارز آن در objective C به شرح زیر است:
leaseStart = [[[aBuilding tenantList:5] leaseDetails] startDate]
نتیجه این عبارت nil است و می تواند تست شود. البته این نیاز به این داشت که تمام فراخوانی های متد dynamic باشند که باعث سربار زیادی می شود. استفاده سوئیفت از اختیاری ها نیز مکانیزم مشابهی برای تست کردن و کار با مقادیر Nil فراهم می کند، اما این کار را به نحوی انجام می دهد که به کامپایلر اجازه می دهد از Static Dispatch استفاده کند، زیرا عمل Unwrapping در یک نمونه تعریف شده (wrapper) فراخوانی شده است و در سیستم runtime Dispatch رخ نداده است.
انواع مقادیر
در بسیاری از زبان های شیء گرا، اشیا به صورت داخلی در دو بخش ارائه می شوند. شی به صورت یک بلوک داده ذخیره شده و در حافظه Heap قرار گرفته است، درحالیکه نام (یا Handle) آن شی توسط یک نشانگر نمایش داده می شود. اشیا با کپی کردن مقدار نشانگر بین متدها ارسال می شوند و به همان داده در Heap اجازه می دهند در دسترس هر کسی که یک کپی دارد، قرار بگیرد. برعکس، Typeهای اصلی مانند اعداد صحیح و اعداد با ممیز شناور مستقیما ارائه می شوند. داده در handle وجود دارد، نه در نشانگر و آن داده مستقیما با کپی شدن به متدها ارسال می شود. به هر دو سبک دسترسی “انتقال از طریق مرجع” برای اشیا و “انتقال با مقدار” برای typeهای اصلی گفته می شود.
هر دو مفهوم دارای مزایا و معایبی هستند. اشیا زمانی مفید هستند که داده بزرگ است، مانند توضیح یک پنجره یا محتوای یک سند. در این موارد، دسترسی به آن داده با کپی کردن یک مقدار 32 یا 64 بیتی فراهم می شود، نه با کپی کردن یک ساختار داده کامل. هرچند مقادیر کوچکتر مانند اعداد صحیح با نشانگرها هم اندازه هستند (معمولا هر دو یک کلمه هستند)، بنابراین مزیتی در انتقال دادن یک نشانگر به جای مقدار وجود ندارد. همچنین انتقال از طریق مرجع نیاز به یک عملیات dereferencing دارد که می تواند در بعضی عملیات ها سربار زیای توضیح کند، معمولا آنهایی که این نوع های مقداری اصلی را دارند، مانند عملیات ریاضیاتی.
زبان برنامه نویسی سوئیفت هم مانند C# و برخلاف بسیاری دیگر از زبان های شی گرا، پشتیبانی داخلی از اشیا با استفاده از قواعد انتقال از طریق مرجع یا انتقال از طریق مقدار دارد. اولی از اعلان class و دومی از struct استفاده میکند. Struct ها در سوئیفت تقریبا تمام ویژگی های کلاس ها را دارند: متدها، استفاده از پروتکل ها و استفاده از مکانیزهای گسترش. به این دلیل شرکت Apple به جای اشیا یا مقادیر، معمولا تمام داده ها را Instance می نامد. البته Struct ها از وراثت پشتیبانی نمی کنند.
برنامه نویس می تواند با آزادی تصمیم بگیرد که کدام قواعد برای هر ساختار داده در برنامه مناسب است. ساختارهای بزرگتر مانند پنجره ها به عنوان کلاس تعریف می شوند تا بتوانند به عنوان نشانگرها منتقل شوند. ساختارهای کوچکتر مانند یک نقطه دو بعدی را می توان به عنوان یک Struct تعریف کرد که توسط مقدار منتقل می شود و اجازه دسترسی مستقیم به داده های داخلی شان را بدون نیاز به dereferencing می دهند. بهبود عملکرد مفهوم انتقال با مقدار به گونه ای است که سوئیفت از این Typeها تقریبا برای تمام انواع داده های عمومی استفاده می کند، از جمله int و double و Typeهایی که معمولا توسط اشیا نمایش داده می شوند، مانند string و Array . استفاده از انواع مقداری همچنین می تواند منجر به بهبود عملکرد چشمگیری در برنامه های کاربری شود.
برای اطمینان از اینکه حتی بزرگترین Structها باعث کاهش کارایی نمی شوند، سوئیفت از روش اشتراک گذاری ضمنی (copy on write) استفاده می کند تا اشیا تنها زمانی کپی شوند که برنامه سعی دارد مقداری را در آنها تغییر دهد. یعنی Accessorهای مختلف در واقع یک نشانگر به همان منبع داده دارند، اما این بسیار پایین تر از سطح زبانی و در واحد مدیریت حافظه (MMU) کامپیوتر صورت می گیرد. بنابراین با اینکه داده به صورت فیزیکی به صورت یک نمونه در حافظه ذخیره شده است، در سطح برنامه این مقادیر مجزا هستند و جداسازی فیزیکی تنها در صورت نیاز توسط روش اشتراک گذاری ضمنی اجرا می شود.
برنامه نویسی پروتکل محور
یکی از ویژگی های اصلی Objective C، پشتیبانی آن از categoryها یا دسته بندی ها است، متدهایی که می توان برای گسترش دادن کلاس ها در زمان اجرا اضافه کرد. دسته بندی ها اجازه گسترش دادن کلاس ها برای اضافه کردن توابع جدید را می دهند و نیازی برای زیرکلاس کردن یا حتی دسترسی داشتن به کد منبع اصلی نیست. یک مثال، اضافه کردن پشتیبانی از spell checker به کلاس مبنای NSString است، یعنی تمام نمونه های NSString در برنامه قابلیت spell checking خواهند داشت. از این سیستم همچنین به طور گسترده ای به عنوان یک تکنیک سازمان دهی استفاده می شود که به کدهای مرتبط اجازه می دهد در ضمیمه هایی کتابخانه مانند گردآوری شوند. زبان برنامه نویسی سوئیفت به پشتیبانی از این قابلیت ادامه می دهد، البته اکنون به آنها Extension گفته می شود و با کلمه کلیدی extension اعلام می شوند. سوئیفت برخلاف Objective C همچنین می تواند Propertyها، Typeها و Enumهای جدیدی به نمونه های موجود اضافه کند.
یکی دیگر از ویژگی های مهم Objective C، استفاده آن از پروتکل ها است که در بیشتر زبان های مدرن به آنها Interface گفته می شود. پروتکل ها وعده می دهند که یک کلاس خاص از یک سری متدها استفاده می کند، یعنی دیگر اشیا در سیستم می توانند آن متدها را روی هر شی ای که از آن پروتکل پشتیبانی می کند، فراخوانی کنند. از این معمولا در زبان های شی گرای مدرن به عنوان یک جایگزین برای وراثت چندگانه استفاده می شود، البته ویژگی های مجموعه ها کاملا یکسان نیستند. یک نمونه رایج از یک پروتکل در Cocoa، پروتکل NSCopying است که یک متد copyWithZone را تعریف می کند که از کپی عمیق روی اشیا استفاده می کند.
در Objective C و بیشتر زبان های دیگر که از مفهوم پروتکل استفاده می کنند، وظیفه برنامه نویس است که مطمئن شود متدهای مورد نیاز در هر کلاس بکار گرفته شده اند. زبان برنامه نویسی سوئیفت قابلیت اضافه کردن این متدها از طریق Extensionها و استفاده از برنامه نویسی جامع (generics) برای بکارگیری آنها را می دهد. با ترکیب اینها می توان پروتکل را تنها یک بار نوشت و از انوع Instanceها پشتیبانی کرد. همچنین می توان از مکانیزم Extension استفاده کرد تا تابعیت از پروتکل را به شی ای اضافه کرد که آن پروتکل در لیستش تعریف نشده است. برای مثال، یک پروتکل که می تواند اعلام شود SupportsToString نام دارد که مطمئن می شود نمونه هایی که با پروتکل مطابقت دارند از یک متد toString استفاده می کنند که نتیجه آن یک String است. در سوئیفت می توان این را با چنین کدی اعلام کرد:
protocol SupportsToString { func toString() -> String }
اکنون می توان این پروتکل را بدون دسترسی به منبع کلاس مبنا، به String اضافه کرد:
extension String: SupportsToString { func toString() -> String { return self } }
در زبان برنامه نویسی سوئیفت هم مانند بسیاری از زبان های مدرن که از Interface پشتیبانی می کنند، از پروتکل ها به عنوان typeها می توان استفاده کرد، یعنی متغیرها و متدها را می توان به جای نوع مخصوص آنها، با پروتکل تعریف کرد:
var someSortOfPrintableObject: SupportsToString ... print(someSortOfPrintableObject.toString())
فرقی نمی کند که someSortOfPrintableObject چه نوع نمونه ای است، کامپایلر مطمئن می شود که با پروتکل مطابقت داشته و در نتیجه کد ایمن است. این قاعده همچنین بدین معناست که Collectionها هم می توانند براساس پروتکل ها باشند، مانند let printableArray = [SupportsToString] .
به علت اینکه زبان برنامه نویسی سوئیفت با Structها و کلاس ها به طور یکسانی رفتار می کند، از Extensionها و پروتکل ها به طور گسترده ای در runtime سوئیفت استفاده می شود تا یک API قوی بر مبنای Structها فراهم شود. برای مثال، سوئیفت از یک Extension برای اضافه کردن پروتکل Equatable به بسیاری از Typeهای اصلی اش مانند Stringها و Arayها استفاده می کند و اجازه می دهد با عملکرد == مقایسه شوند. یک نمونه بارز از تعامل تمام این ویژگی ها را می توان در مفهوم بکارگیری پیش فرض پروتکل ها مشاهده کرد:
func !=<T : Equatable>(lhs: T, rhs: T) -> Bool
این تابع یک متد تعریف می کند که در هر نمونه ای که با Equatable مطابقت دارد، کار می کند و یک تابع not equals یا عدم تساوی ارائه می دهد. هر نمونه ای مانند کلاس یا Struct به طور خودکار تنها با مطابقت با Equatable این قابلیت را به دست می آورد. به دلیل اینکه بسیاری از نمونه ها Equatable را از طریق بکارگیری اصلی یا دیگر Extensionهای عمومی به دست می آورند، بیشتر اشیای پایه ای در runtime، تساوی یا عدم تساوی را بدون کد به دست می آورند.
ترکیب پروتکل ها، پیش فرض ها، وراثت پروتکل و Extensionها به بسیاری از توابعی که معمولا با کلاس ها و وراثت ها ارتباط دارند اجازه می دهد روی نوع های مقداری اجرا شوند. اگر از این قابلیت به درستی استفاده شود، می تواند منجر به بهبود چشمگیر عملکرد بدون هیچ محدودیت آشکاری در API شود. آنقدر از این مفهوم به طور گسترده در زبان برنامه نویسی سوئیفت استفاده می شود که شرکت Apple آن را زبان برنامه نویسی پروتکل محور نامیده است. آنها توصیه کرده اند بسیاری از مشکلاتی که معمولا از طریق کلاس ها و وراثت حل می شوند، با استفاده از پروتکل ها و Structها رفع شوند.
کتابخانه ها، runtime و توسعه
زبان برنامه نویسی سوئیفت از یک runtime مشابه با سیستم موجود Objective C استفاده می کند، اما نیاز به iOS 7 یا macOS 10.9 یا بالاتر دارد. از کد سوئیفت یا Objective C می توان در یک برنامه استفاده کرد و در نتیجه از C و C++ نیز می توان استفاده کرد. برخلاف C، کد C++ را نمی توان مستقیما از داخل سوئیفت استفاده کرد. یک Wrapper در Objective C یا C باید بین سوئیفت و C++ ساخته شود. در مورد Objective C، سوئیفت دسترسی گسترده ای به مدل شی دارد و می تواند برای زیرکلاس کردن، بسط دادن و استفاده از کد Objective C برای فراهم کردن پشتیبانی از پروتکل، استفاده شود. برعکس آن صحت ندارد. یک کلاس سوئیفت را نمی توان در Objective C زیرکلاس کرد.
برای کمک به توسعه چنین برنامه هایی و استفاده از کدهای موجود، Xcode 6 یک سیستم نیمه خودکار ارائه می کند که یک bridging header را ایجاد و حفظ می کند تا کد Objective C را برای سوئیفت فراهم کند. این به صورت یک فایل Header مجزا است که تمام نمادهای Objective C که توسط کد سوئیفت مورد نیاز هستند را تعریف یا Import می کند. در این مرحله سوئیفت می تواند به Typeها، توابع و متغیرهایی که در آن Importها تعریف شده اند اشاره داشته باشد، به طوری که انگار در سوئیفت نوشته شده اند. همچنین کد Objective C می تواند مستقیما از کد سوئیفت استفاده کند و یک فایل Header با اعلان های Objective C از نمادهای پروژه سوئیفت را به طور خودکار Import کند. برای مثال، یک فایل Objective C در یک پروژه ترکیبی به نام MyApp می تواند با کد #import “MyApp-Swift.h” به کلاس ها یا توابع سوئیفت دسترسی داشته باشد. البته تمام کدها از طریق این مکانیزم موجود نیستند. استفاده از ویژگی های مخصوص سوئیفت مانند نوع های Generic، نوع های اختیاری غیر شی، enumهای پیچیده و حتی شناسه های یونیکد ممکن است نمادی را رندر کنند که که از طریق Objective C غیر قابل دسترسی است.
همچنین زبان برنامه نویسی سوئیفت پشتیبانی محدودی برای Attributeها یا خصیصه ها دارد، یعنی متادیتاهایی که توسط محیط توسعه خوانده می شوند و لزوما بخشی از کد کامپایل شده نیستند. مانند Objective C، Attributeها از قاعده @ استفاده می کنند، اما مجموعه موجود کنونی بسیار کوچک است. یک مثال، خصیصه @IBOutlet است که یک مقدار معین در کد را به عنوان یک outlet یا خروجی علامت گذاری می کند که از داخل Interface Builder (IB) قابل استفاده است. outlet یک دستگاهی است که مقدار نمایش روی صفحه را به یک شی در کد متصل می کند.
مدیریت حافظه
زبان برنامه نویسی سوئیفت از شمارش مرجع اتوماتیک (ARC) برای مدیریت حافظه استفاده می کند. Apple در گذشته نیاز به مدیریت حافظه دستی در Objective C داشت، اما ARC را در سال 2011 معرفی کرد که اجازه تخصیص و آزادسازی راحت تر حافظه را می دهد. یکی از مشکلات ARC، احتمال ایجاد یک چرخه مرجع قوی است که نمونه های دو کلاس مختلف هر کدام به دیگری ارجاع دارند که باعث می شود در حافظه نشت کنند، زیرا هرگز آزاد نمی شوند. زبان برنامه نویسی سوئیفت کلمات کلیدی weak و unowned را فراهم کرده است تا از چرخه های مرجع قوی خودکاری شود. عموما یک رابطه پدر – فرزندی از مرجع قوی استفاده می کند، درحالیکه یک رابطه فرزند – پدری یا از یک مرجع weak استفاده می کند که عناصر پدر و فرزند می توانند با هم نامرتبط باشند، یا از unowned استفاده می کند که یک فرزند همیشه یک پدر دارد، اما پدر ممکن است فرزندی نداشته باشد. مرجع های weak باید متغیرهای اختیاری باشند، زیرا می توانند تغییر کنند و nil شوند. یک closure درون یک کلاس نیز می تواند با گرفتن ارجاعات به خود، یک چرخه مرجع قوی ایجاد کند. ارجاعات به خود را می توان با استفاده از یک Capture List به عنوان weak یا unowned در نظر گرفت.
عیب یابی و عناصر دیگر
یک عنصر اصلی در سیستم سوئیفت، قابلیت آن برای عیب یابی شدن کامل و اجرا شدن در محیط توسعه با استفاده از یک read–eval–print loop (REPL) است که به آن خصوصیات تعاملی می دهد که بیشتر به قابلیت های اسکریپت نویسی python شباهت دارد تا زبان های برنامه نویسی سیستم سنتی. REPL با مفهوم جدید Playground ها بیشتر توسعه یافته است. اینها نماهای تعاملی هستند که در محیط Xcode اجرا می شوند و به تغییرات کد و Debugger به طور لحظه ای واکنش نشان می دهند. اگر بعضی از کدها به مرور زمان یا نسبت به دیگر مقادیر ورودی تغییر کنند، از نما می توان به همراه Timeline Assistant استفاده کرد تا خروجی را به صورت انیمیشنی نمایش داد. شرکت Apple ادعا می کند که سوئیفت اولین زبان برنامه نویسی سیستم صنعتی است که به اندازه یک زبان اسکریپت نویسی رسا و لذت بخش است.
شباهت ها با زبان C
- بیشتر عملگرهای C در سوئیفت استفاده شده اند، اما عملگرهای جدیدی هم اضافه شده اند.
- از آکولادها برای گروه بندی عبارات استفاده می شود.
- متغیرها با یک علامت مساوی تخصیص می یابند، اما با استفاده از دو علامت مساوی پشت هم مقایسه می شوند. یک عملگر هویت جدید === فراهم شده است که بررسی می کند دو عنصر داده به یک شی اشاره دارند یا نه.
- عبارت کنترلی while ، if و switch مشابه هم هستند، اما قابلیت های بیشتری دارند. برای مثال، یک switch که اعداد غیرصحیح را دریافت می کند، while و if از مطابقت الگو و unwrap کردن شرطی اختیاری ها پشتیبانی می کنند و غیره.
شباهت ها با Objective C
- انواع عددی مبنا (Int، UInt، Float، Double )
- از کروشه ها برای آرایه ها استفاده می شود تا آنها را اعلام کنند و یک مقدار از یک شاخص معین را از یکی از آنها بگیرند.
- متدهای کلاس به ارث برده می شوند، مانند متدهای Instance. Self در متدهای کلاس، همان کلاسی است که متد در آن فراخوانی شده است.
- قاعده شمارشی مشابه for …in
تفاوت ها با Objective C
- عبارات نیازی نیست با نقطه ویرگول (؛ ) به پایان برسند، اما برای نوشتن بیش از یک عبارت در یک خط با از آن استفاده شود.
- عدم وجود فایل header.
- استنباط کردن نوع.
- برنامه نویسی Generic.
- توابع، اشیای درجه یک هستند.
- Enumerationها می توانند داده های مرتبط داشته باشند (داده های جبری).
- عملگرها را می توان برای کلاس ها مجددا تعریف کرد (سربارگذاری عملگرها) و عملگرهای جدیدی را می توان تعریف کرد.
- Stringها کاملا از یونیکد پشتیبانی می کنند. بیشتر کاراکترهای یونیکد را می توان در شناسه ها یا عملگرها استفاده کرد.
- عدم مدیریت استثنا. سوئیفت 2 یک مدل مدیریت خطای متفاوت و ناسازگار را معرفی کرده است.
- چند رفتار مستعد در برابر خطا در زبان های خانواده C تغییر یافته اند.
- نشانگرها به طور پیش فرض آشکار نیستند. برنامه نویس نیازی ندارد اسم ها را برای Reference و Derefence کردن پیگیری کند.
- Assignmentها مقداری حاصل نمی کنند. این کار با دادن خطا در زمان کامپایل کردن، از خطای رایج نوشتن i = 0 به جای i == 0 جلوگیری می کند.
- نیازی به استفاده از عبارات break در بلوک های switch وجود ندارد. Caseهای انفرادی به Case بعدی نمی روند، مگر اینکه از عبارت fallthrough استفاده شده باشد.
- متغیرها و ثابت ها همیشه مقداردهی اولیه شده اند و آرایه ها همیشه بررسی شده اند.
- سرریزهای عدد صحیح که منجر به رفتارهای نامشخص برای اعداد صحیح امضا شده در C می شوند به عنوان یک خطای runtime در سوئیفت مشخص شده اند. برنامه نویس ها می توانند با استفاده از عملگرهای مخصوص ریاضیاتی &+ ,، &- ,، &* ,، &/ و &% اجازه سرریز را بدهند. مشخصه های min و max در سوئیفت برای تمام انواع عدد صحیح تعریف شده اند و می توان از آنها استفاده کرد تا به طور ایمن سرریزهای احتمالی را چک کرد و نیازی به تکیه بر ثابت هایی که برای هر نوع در کتابخانه های اکسترنال تعریف شده اند، نیست.
- شکل انفرادی if و while که اجازه حذف کروشه ها از عبارات را می دهد، پشتیبانی نشده است.
- Enumeration به سبک سی for (int i = 0; i < c; i++) که در معرض خطاهای off-by-one است پشتیبانی نشده است (از سوئیفت 3 به بعد).
- عملگرهای کاهش و افزایش پس و پیش (i++ ، –i و …) پشتیبانی نشده اند (از سوئیفت 3 به بعد)، مخصوصا از زمانی که عبارات for به سبک C از سوئیفت 3 به بعد پشتیبانی نمی شوند.
کد نمونه
// This is one line comment using two slashes /* This is also a comment, but written over multiple lines */ /* Multiline comments /* can be nested! */ Thus, code containing multiline comments can be blocked out */ // Swift variables are declared with "var" // This is followed by a name, a type, and a value var explicitDouble: Double = 70 // If the type is omitted, Swift will infer it from // the variable's initial value var implicitInteger = 70 var implicitDouble = 70.0 var 國 = "美國" var 🌎 = "🐝🐙🐧🐨🐸" // Swift constants are declared with "let" // followed by a name, a type, and a value let numberOfBananas: Int = 10 // Like variables, if the type of a constant is omitted, // Swift will infer it from the constant's value let numberOfApples = 3 let numberOfOranges = 5 // Values of variables and constants can both be // interpolated in strings as follows let appleSummary = "I have \(numberOfApples) apples." let fruitSummary = "I have \(numberOfApples + numberOfOranges) pieces of fruit." // In "playgrounds", code can be placed in the global scope print("Hello, world") // This is an array variable var fruits = ["mango", "kiwi", "avocado"] // Example of an if statement; .isEmpty, .count if fruits.isEmpty { print("No fruits in my array.") } else { print("There are \(fruits.count) items in my array") } // Define a dictionary with four items: // Each item has a person's name and age let people = ["Anna": 67, "Beto": 8, "Jack": 33, "Sam": 25] // Now use Swift's flexible enumerator system // to extract both values in one loop for (name, age) in people { print("\(name) is \(age) years old.") } // Functions and methods are both declared with the // "func" syntax, and the return type is specified with -> func sayHello(personName: String) -> String { let greeting = "Hello, \(personName)!" return greeting } // prints "Hello, Dilan!" print(sayHello(personName: "Dilan")) // Parameter names can be made external and required // for calling. // The external name can be the same as the parameter // name (by doubling up) // - or it can be defined separately. func sayAge(personName personName: String, personAge age: Int) -> String { let result = "\(personName) is \(age) years old." return result } // We can also specify the name of the parameter print(sayAge(personName: "Dilan", personAge: 42))
منابع: ویکی پدیا انگلیسی ، وبسایت Swift ، آریا گستر و …
توصیه می کنیم دوره های جامع فارسی مرتبط با این موضوع آریاگستر را مشاهده کنید:
– صفر تا صد آموزش سوئیفت و برنامه نویسی اپل
– محصولات آموزشی مرتبط با برنامه نویسی
توجه : مطالب و مقالات وبسایت آریاگستر تماما توسط تیم تالیف و ترجمه سایت و با زحمت فراوان فراهم شده است . لذا تنها با ذکر منبع آریا گستر و لینک به همین صفحه انتشار این مطالب بلامانع است !
دوره های آموزشی مرتبط
390,000 تومان
قوانین ارسال دیدگاه در سایت