آشنایی با سوئیفت (بخش دوم)
آخرین به روزرسانی در 21/10/2022
در بخش دوم از آموزش سوئیفت قصد داریم به ادامه ی بخش قبلی و ساختار زبان سوئیفت بپردازیم.
ما در بخش اول آموزش به مفاهیم اولیه و ویژگی های سوئیفت تا توابع ، حلقه ها ، ثابت ها ، عملگرها و … پرداختیم.
و در این بخش قصد داریم به ادامه ی مفاهیم داده ها ، ساختارها ، کلاس ها و … بپردازیم.
پس برای تکمیل این آموزش با ما همراه باشید.
لازم به ذکر است پیش نیاز این بخش از آموزش مطلاعه ی بخش اول آشنایی با سوئیفت می باشد.
Closures
Closures در سوئیفت 4 شبیه توابع مستقلی است که به صورت بلوک سازماندهی شده و در هر جایی مانند زبان های C و Objective C فراخوانی می شوند.
ارجاعات ثابت و متغیری که در داخل توابع تعریف شده اند در Closure ها ذخیره می شوند.
توابع به عنوان موارد خاص Closures در نظر گرفته می شوند و به سه شکل زیر قرار دارند :
Global Functions | Nested Functions | Closure Expressions |
---|---|---|
هیچ مقداری را ثبت نکنید | گرفتن مقادیر از تابع enclosing | پکیج های بدون نام، مقادیر بلوک های مجاور را می گیرند. |
Closure expressions در زبان سوئیفت 4 از موارد زیر پیروی می کند :
- استنتاج پارامترها و انواع مقادیر برگردانده از متن.
- بازده Implicit از single-expression closures
- اسامی آرگومان های کوتاه
- سینتکس Trailing closure
سینتکس
در زیر یک دستور عمومی برای تعریف closure است که پارامترها را می پذیرد و یک نوع داده را برمی گرداند :
{
(parameters) −> return type in
statements
}
مثال :
let studname = { print("Welcome to Swift Closures") }
studname()
خروجی :
Welcome to Swift Closures
closure زیر دو پارامتر را می پذیرد و یک مقدار Bool را برمی گرداند.
{
(Int, Int) −> Bool in
Statement1
Statement 2
---
Statement n
}
مثال :
let divide = {
(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
خروجی :
10
Expressions in Closures
توابع تو در تو راه مناسبی برای نام گذاری و تعریف بلوک های کد ارائه می دهند.
به جای نمایش کل اعلان تابع و name constructs برای نشان دادن توابع کوتاهتر استفاده می شود.
نمایش تابع در یک عبارت کوتاه واضح با سینتکس متمرکز از طریق closure expressions به دست می آید.
برنامه سفارش صعودی
مرتب سازی یک رشته توسط تابع reserved سوئیفت 4 “sorted” انجام می شود که از قبل در کتابخانه استاندارد موجود است.
تابع رشته های داده شده را به ترتیب صعودی مرتب می کند و عناصر را در یک آرایه جدید با همان اندازه و نوع داده ذکر شده در آرایه قدیمی برمی گرداند.
آرایه قدیمی به همان صورت باقی می ماند.
دو آرگومان در داخل تابع مرتب شده ، نشان داده شده است.
مقادیر از نوع شناخته شده به صورت آرایه نمایش داده می شوند.
محتویات آرایه (Int، Int) و یک مقدار Boolean (Bool) برمی گرداند ، اگر آرایه به درستی مرتب شده باشد ، مقدار واقعی را برمی گرداند در غیر این صورت false را برمی گرداند.
یک تابع معمولی با رشته ورودی نوشته شده و به تابع مرتب شده ارسال می شود تا رشته ها به آرایه جدیدی که در زیر نشان داده شده است مرتب شوند.
func ascend(s1: String, s2: String) -> Bool {
return s1 > s2
}
let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)
خروجی :
true
آرایه initial که باید برای icecream مرتب شود به عنوان “Swift 4” و “great” داده شده است.
تابع مرتب سازی آرایه به عنوان نوع داده رشته ای و نوع برگشتی آن به عنوان Boolean ذکر می شود.
هر دو رشته با هم مقایسه و به ترتیب صعودی مرتب شده و در یک آرایه جدید ذخیره می شوند.
اگر مرتبسازی با موفقیت انجام شود ، تابع مقدار واقعی را برمیگرداند در غیر این صورت false را برمیگرداند.
سینتکس Closure expression از موارد زیر ، استفاده می کند :
- پارامترهای ثابت
- پارامترهای متغیر
- پارامترهای inout
Closure expression از مقادیر پیش فرض پشتیبانی نمی کند.
پارامترهای Variadic و Tuples نیز می توانند به عنوان انواع پارامترها و انواع برگشتی استفاده شوند.
let sum = {
(no1: Int, no2: Int) -> Int in
return no1 + no2
}
let digits = sum(10, 20)
print(digits)
خروجی :
30
پارامترها و اعلانهای نوع بازگشتی که در سینتکس تابع ذکر شدهاند نیز میتوانند با تابع closure expression درون خطی با کلمه کلیدی “in” نمایش داده شوند.
پس از اعلام پارامتر و نوع بازگشت ، از کلمه کلیدی “in” برای نشان دادن آن بادی closure استفاده می شود.
Single Expression Implicit Returns
در اینجا، نوع تابع دوم آرگومان مرتب شده ، روشن می کند که یک مقدار Bool باید با closure بازگردانده شود.
از آنجا که بادی closure شامل یک عبارت واحد (s1 > s2) است که یک مقدار Bool را برمیگرداند، هیچ ابهامی وجود ندارد و کلمه کلیدی بازگشتی را میتوان حذف کرد.
برای برگرداندن یک Single expression در expression closures ، کلمه کلیدی ‘return’ در قسمت اعلان آن حذف می شود.
var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })
print(descending)
print(ascending)
خروجی :
[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]
خود دستور به وضوح تعریف میکند که وقتی string1 بزرگتر از رشته 2 است، true باشد در غیر این صورت false، بنابراین عبارت return در اینجا حذف میشود.
Known Type Closures
جمع دو عدد را در نظر بگیرید.
می دانیم که جمع، نوع داده عدد صحیح را برمی گرداند.
از این رو closures های نوع شناخته شده به صورت زیر اعلام می شوند :
let sub = {
(no1: Int, no2: Int) -> Int in
return no1 - no2
}
let digits = sub(10, 20)
print(digits)
خروجی :
-10
اعلان نامهای Shorthand Argument به عنوان Closures
سوئیفت 4 به طور خودکار نامهای Shorthand Argument را برای بستههای درون خطی ارائه میکند، که میتوان از آنها برای اشاره به مقادیر آرگومانهای Closures با نامهای $0، $1، $2 و … استفاده کرد.
var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))
در اینجا $0 و $1 به آرگومان های رشته اول و دوم closure اشاره دارد.
خروجی :
200
سوئیفت 4 کاربر را تسهیل میکند تا closures Inline را بهعنوان نام shorthand argument با نشان دادن $0 ، $1 ، $2 — $n نشان دهد.
هنگامی که نام آرگومان های مختصر را در داخل closure expressions نمایش می دهیم، فهرست آرگومان های closure در بخش defined حذف می شود.
بر اساس نوع تابع ، نام آرگومان مختصر مشتق خواهد شد.
از آنجایی که آرگومان مختصر در بادی expressions تعریف شده است ، کلمه کلیدی ‘in’ حذف می شود.
Closures به عنوان توابع Operator
سوئیفت 4 تنها با ارائه عملکردهای اپراتور به عنوان Closures ، راه آسانی برای دسترسی به اعضا فراهم می کند.
در مثالهای قبلی، کلمه کلیدی «Bool» برای برگرداندن «true» زمانی که رشتهها برابر هستند استفاده میشود ، در غیر این صورت «false» را برمیگرداند.
این expression توسط تابع عملگر در حالت زیر سادهتر میشود :
let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
(left: Int, right: Int) -> Bool in
return left < right
})
let asc = numb.sorted(<)
print(asc)
خروجی :
[-30, -20, 18, 35, 42, 98]
Closures به عنوان تریلر
ارسال آرگومان نهایی تابع به یک closure expression با کمک “Trailing Closures” اعلام می شود.
خارج از تابع () با {} نوشته می شود.
استفاده از آن زمانی مورد نیاز است که امکان نوشتن تابع به صورت درون خطی در یک خط وجود نداشته باشد.
reversed = sorted(names) { $0 > $1}
که در آن {$0 > $1} بهعنوان closure های انتهایی اعلام شده در خارج (names) نشان داده میشوند.
import Foundation
var letters = ["North", "East", "West", "South"]
let twoletters = letters.map({
(state: String) -> String in
return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
let stletters = letters.map() {
$0.substringToIndex(advance($0.startIndex, 2)).uppercaseString
}
print(stletters)
خروجی :
[NO, EA, WE, SO]
گرفتن مقادیر و انواع Reference
در سوئیفت 4، گرفتن مقادیر ثابت و متغیر با کمک closure ها انجام می شود.
همچنین مقادیر آن ثابت ها و متغیرهای داخل بادی closure را ارجاع داده و تغییر می دهد، حتی اگر متغیرها دیگر وجود نداشته باشند.
گرفتن مقادیر ثابت و متغیر با استفاده از تابع تو در تو با نوشتن تابع در بادی تابع دیگر به دست می آید.
یک تابع تو در تو موراد زیر را می گیرد :
- آرگومان های تابع بیرونی
- ثابت ها و متغیرهای تعریف شده در تابع Outer را ضبط کنید.
در سوئیفت 4، هنگامی که یک ثابت یا یک متغیر در داخل یک تابع اعلان می شود، به آن متغیرها نیز به طور خودکار با closure ارجاع داده می شود.
همچنین این امکان را برای ارجاع بیش از دو متغیر به عنوان closure یکسان به شرح زیر فراهم می کند :
let decrem = calcDecrement(forDecrement: 18)
decrem()
در اینجا متغیرهای oneDecrement و Decrement هر دو همان بلوک حافظه را به عنوان رفرنس closure نشان می دهند.
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 100
func decrementer() -> Int {
overallDecrement -= total
print(overallDecrement)
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()
خروجی :
82
64
46
هنگامی که هر بار تابع خارجی calcDecrement فراخوانی می شود، تابع () decrementer را فراخوانی می کند و مقدار را 18 کاهش می دهد و نتیجه را با کمک تابع خارجی calcDecrement برمی گرداند.
در اینجا calcDecrement به عنوان یک closure عمل می کند.
حتی اگر تابع () decrementer هیچ آرگومانی ندارد، closure به طور پیشفرض به متغیرهای ‘overallDecrement’ و ‘total’ با گرفتن مقادیر موجود آن اشاره میکند.
کپی مقادیر متغیرهای مشخص شده با تابع () new decrementer ذخیره می شود.
Swift 4 عملکردهای مدیریت حافظه را با تخصیص فضاهای حافظه در زمانی که متغیرها در حال استفاده نیستند مدیریت می کند.
Enumerations
شمارش یک نوع داده تعریف شده توسط کاربر است که از مجموعه ای از مقادیر مرتبط تشکیل شده است.
کلمه کلیدی enum برای نوع داده های شمارش شده تعریف شده استفاده می شود.
قابلیت شمارش
Enumeration در سوئیفت 4 نیز شبیه ساختار C و Objective C است.
در یک کلاس اعلان می شود و مقادیر آن از طریق نمونه آن کلاس قابل دسترسی است.
مقدار عضو اولیه با استفاده از مقداردهی کننده های enum تعریف می شود.
عملکرد آن نیز با اطمینان از عملکرد پروتکل استاندارد گسترش یافته است.
سینتکس
شمارش ها با کلمه کلیدی enum معرفی می شوند و کل تعریف خود را در یک جفت پرانتز قرار می دهند :
enum enumname {
// enumeration values are described here
}
به عنوان مثال، شما می توانید یک شمارش برای روزهای هفته به صورت زیر تعریف کنید :
enum DaysofaWeek {
case Sunday
case Monday
---
case Saturday
}
مثال :
enum names {
case Swift
case Closures
}
var lang = names.Closures
lang = .Closures
switch lang {
case .Swift:
print("Welcome to Swift")
case .Closures:
print("Welcome to Closures")
default:
print("Introduction")
}
خروجی :
Welcome to Closures
شمارش سوئیفت 4 مقدار پیشفرض اعضای خود را مانند C و هدف C تعیین نمیکند.
در عوض، اعضا به صراحت با نام شمارش آنها تعریف میشوند.
نام شمارش باید با حرف بزرگ شروع شود (مثلاً: enum DaysofaWeek).
var weekDay = DaysofaWeek.Sunday
در اینجا Enumeration با ‘DaysofaWeek’ به یک متغیر weekday.Sunday اختصاص داده شده است.
به کامپایلر اطلاع می دهد که نوع داده متعلق به یکشنبه (Sunday) به اعضای enum بعدی آن کلاس خاص اختصاص داده می شود.
هنگامی که نوع داده عضو enum تعریف شد، می توان با ارسال مقادیر و محاسبات بیشتر به اعضا دسترسی داشت.
شمارش با Switch Statement
عبارت Switch نیز از انتخاب multi way پیروی می کند.
فقط یک متغیر در یک زمان خاص بر اساس شرایط مشخص شده قابل دسترسی است.
حروف پیشفرض در دستور switch برای به دام انداختن موارد نامشخص استفاده میشود.
enum Climate {
case India
case America
case Africa
case Australia
}
var season = Climate.America
season = .America
switch season {
case .India:
print("Climate is Hot")
case .America:
print("Climate is Cold")
case .Africa:
print("Climate is Moderate")
case .Australia:
print("Climate is Rainy")
}
خروجی :
Climate is Cold
برنامه ابتدا Climate را به عنوان نام شمارش تعریف می کند.
سپس اعضای آن مانند «هند»، «آمریکا»، «آفریقا» و «استرالیا» متعلق به کلاس «Climate» اعلام میشوند.
اکنون عضو America به یک متغیر فصلی اختصاص داده شده است.
علاوه بر این، Switch case مقادیر مربوط به America را می بیند و به آن عبارت خاص منشعب می شود.
خروجی به صورت “Climate is Cold” نمایش داده می شود.
به همین ترتیب می توان از طریق دستورات سوئیچ به همه اعضا دسترسی داشت.
هنگامی که شرایط برآورده نمی شود ، به طور پیش فرض «Climate is not predictable» چاپ می شود.
شمارش را می توان بیشتر به مقادیر مرتبط و مقادیر خام طبقه بندی کرد.
تفاوت بین Associated Values و Raw Values
Associated Values | Raw Values |
Different Datatypes | Same Datatypes |
Ex: enum {10,0.8,”Hello”} | Ex: enum {10,35,50} |
Values are created based on constant or variable | Prepopulated Values |
Varies when declared each time | Value for member is same |
Enum با مقادیر مرتبط
enum Student {
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
خروجی :
Student Marks are: 98,97,95.
به عنوان مثال دسترسی به نام دانشآموز و علامتهای ایمنشده در سه موضوع را در نظر بگیرید، نام شمارش بهعنوان دانشآموز اعلام میشود و اعضای حاضر در کلاس enum، نامی هستند که متعلق به نوع داده رشتهای هستند، علائم بهصورت mark1، mark2 و mark3 از نوع داده Integer نمایش داده میشوند.
برای دسترسی به نام دانش آموز یا نمرات آنها.
var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)
حال، کیس سوئیچ نام دانش آموز را در صورتی که بلوک مورد اجرا شود چاپ می کند، در غیر این صورت علائم ایمن شده توسط دانش آموز را چاپ می کند.
اگر هر دو شرط ناموفق باشند، بلوک پیش فرض اجرا می شود.
Enum با Raw Values
Raw values می توانند رشته ها، کاراکترها یا هر یک از انواع عدد صحیح یا ممیز FLOAT باشند.
هر مقدار خام باید در اعلان شمارش منحصر به فرد باشد.
وقتی از اعداد صحیح برای Raw values استفاده می شود، اگر مقداری برای برخی از اعضای شمارش مشخص نشده باشد، به طور خودکار افزایش می یابند.
enum Month: Int {
case January = 1, February, March, April, May, June, July, August,
September, October, November, December
}
let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")
خروجی :
Value of the Month is: 5.
Structures
سوئیفت 4 یک بلوک ساختمانی انعطاف پذیر برای استفاده از سازه ها به عنوان Structures فراهم می کند.
با استفاده از این ساختارها یک بار می توان روش ها و ویژگی های سازه ها را تعریف کرد.
برخلاف C و Objective C
- Structure نیازی به implementation files و رابط ندارد.
- Structure به ما اجازه می دهد یک فایل واحد ایجاد کنیم و رابط آن را به طور خودکار به بلوک های دیگر گسترش دهیم.
- در Structure مقادیر متغیر کپی شده و در کدهای بعدی با برگرداندن یک کپی از مقادیر قدیمی ارسال می شود تا مقادیر تغییر نکنند.
Structures are defined with a 'Struct' Keyword.
struct nameStruct {
Definition 1
Definition 2
---
Definition N
}
تعریف یک Structure
برای مثال ، فرض کنید باید به رکورد دانشآموزان شامل نمرههای سه موضوع دسترسی داشته باشیم و مجموع سه موضوع را دریابیم.
در اینجا markStruct برای مقداردهی اولیه یک ساختار با سه علامت به عنوان نوع داده “Int” استفاده می شود.
struct MarkStruct {
var mark1: Int
var mark2: Int
var mark3: Int
}
دسترسی به ساختار و ویژگی های آن
اعضای ساختار با نام structure آن قابل دسترسی هستند.
نمونه های structure با کلمه کلیدی “let” مقداردهی اولیه می شوند.
struct studentMarks {
var mark1 = 100
var mark2 = 200
var mark3 = 300
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
خروجی :
Mark1 is 100
Mark2 is 200
Mark3 is 300
نشانه های دانش آموزان با نام ساختار “studentMarks” قابل دسترسی است.
اعضای ساختار به صورت mark1، mark2، mark3 با مقادیر نوع صحیح مقداردهی اولیه می شوند.
سپس ساختار () studentMarks با کلمه کلیدی “let” به علامت ها منتقل می شود.
علامتهای بعدی حاوی مقادیر اعضای structure خواهند بود.
اکنون مقادیر با دسترسی به مقادیر اعضای structure توسط ‘.’ چاپ می شوند.
struct MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97
print(aStruct.mark) // 98
print(bStruct.mark) // 97
خروجی :
enum Climate {
case India
case America
case Africa
case Australia
}
var season = Climate.America
season = .America
switch season {
case .India:
print("Climate is Hot")
case .America:
print("Climate is Cold")
case .Africa:
print("Climate is Moderate")
case .Australia:
print("Climate is Rainy")
}
خروجی :
98
97
بهترین شیوه های استفاده از Structure ها
زبان سوئیفت 4 عملکردی را برای تعریف ساختارها به عنوان انواع داده های سفارشی برای ساخت بلوک های تابع فراهم می کند.
نمونه های ساختار با مقدار آن به بلوک های تعریف شده برای دستکاری های بیشتر منتقل می شوند.
نیاز به داشتن ساختارها
برای encapsulate کردن مقادیر ساده داده ها.
برای کپی کردن دادههای encapsulate شده و ویژگیهای مرتبط با آن با «values» به جای «references».
ساختار “کپی” و “references“.
ساختارها در سوئیفت 4 به جای رفرنس ها ، مقادیر خود را به اعضای خود منتقل می کنند.
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)
خروجی :
98
96
100
مثال دیگر :
struct markStruct {
var mark1: Int
var mark2: Int
var mark3: Int
init(mark1: Int, mark2: Int, mark3: Int) {
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)
print(fail.mark1)
print(fail.mark2)
print(fail.mark3)
خروجی :
34
42
13
ساختار “markStruct” ابتدا با اعضای آن mark1، mark2 و mark3 تعریف می شود.
اکنون متغیرهای کلاس های عضو برای نگهداری مقادیر صحیح مقداردهی اولیه می شوند.
سپس کپی اعضای structure با کلمه کلیدی ‘self’ ایجاد می شود.
هنگامی که کپی اعضای structure ایجاد می شود، بلوک structure با علائم پارامتر آن به متغیر ‘marks‘ منتقل می شود که اکنون علائم دانش آموزان را نگه می دارد.
سپس علامتها به صورت 98، 96، 100 چاپ میشوند.
مرحله بعدی برای اعضای structure یکسان، نمونه دیگری به نام «fail» استفاده میشود تا به اعضای ساختار مشابه با علامتهای متفاوت اشاره شود.
سپس نتایج اکنون به صورت 34، 42، 13 چاپ میشوند.
این به وضوح توضیح میدهد که structure ها یک کپی از متغیرهای عضو خواهند داشت و سپس اعضا را به بلوکهای تابع بعدی خود منتقل میکنند.
کلاس ها
کلاسهای Swift 4 بلوکهای building ساختارهای انعطافپذیر هستند.
مشابه ثابت ها ، متغیرها و توابع ، کاربر می تواند ویژگی ها و متدهای کلاس را تعریف کند.
سوئیفت 4 عملکردی را در اختیار ما قرار می دهد که در هنگام اعلان کلاس ها ، کاربران نیازی به ایجاد رابط یا فایل های پیاده سازی ندارند.
سوئیفت 4 به ما اجازه میدهد تا کلاسها را بهعنوان یک فایل واحد ایجاد کنیم و پس از مقداردهی اولیه کلاسها ، رابطهای خارجی بهطور پیشفرض ایجاد میشوند.
مزایای کلاس ها
- وراثت ویژگی های یک کلاس را به کلاس دیگر می دهد
- نوع ریخته گری کاربر را قادر می سازد تا نوع کلاس را در زمان اجرا بررسی کند
- Deinitializers از آزادسازی منابع حافظه مراقبت می کنند
- شمارش رفرنس به نمونه کلاس اجازه می دهد تا بیش از یک رفرنس داشته باشد
ویژگی های مشترک کلاس ها و ساختارها :
- Propertie ها برای ذخیره مقادیر تعریف می شوند
- Subscript ها برای دسترسی به مقادیر تعریف شده اند
- متد ها برای بهبود عملکرد مقداردهی اولیه می شوند
- Initial state توسط مقداردهی اولیه تعریف می شود
- عملکرد فراتر از مقادیر پیش فرض گسترش یافته است
- تایید استانداردهای عملکرد پروتکل
Class classname {
Definition 1
Definition 2
---
Definition N
}
تعریف یک کلاس
class student {
var studname: String
var mark: Int
var mark2: Int
}
خروجی :
let studrecord = student()
مثال :
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark = 300
}
let marks = studentMarks()
print("Mark is \(marks.mark)")
خروجی :
Mark is 300
دسترسی به پراپرتی های کلاس به عنوان انواع مرجع
ویژگی های کلاس را می توان با ‘.’ در دسترس قرار داد.
سینتکس Property با یک “.” از هم جدا شده است.
بعد از نام instance :
class MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
class studentMarks {
var mark1 = 300
var mark2 = 400
var mark3 = 900
}
let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")
خروجی :
Mark1 is 300
Mark2 is 400
Mark3 is 900
Class Identity Operators
کلاسها در سوئیفت 4 به چندین ثابت و متغیر اشاره میکنند که به یک نمونه واحد اشاره میکنند.
برای اطلاع از ثابت ها و متغیرهایی که به یک نمونه کلاس خاص اشاره می کنند از عملگرهای هویت استفاده می شود.
نمونه های کلاس همیشه با مرجع ارسال می شوند.
در کلاسهای NSString، NSArray و نمونههای NSDictionary همیشه بهجای یک کپی، بهعنوان ارجاع به یک نمونه موجود تخصیص داده میشوند و منتقل میشوند.
Identical to Operators | Not Identical to Operators |
---|---|
Operator used is (===) | Operator used is (!==) |
زمانی که دو ثابت یا متغیر به یک نمونه اشاره می کنند، مقدار true را برمی گرداند. | زمانی که دو ثابت یا متغیر به یک نمونه متفاوت اشاره می کنند، مقدار true را برمی گرداند. |
class SampleClass: Equatable {
let myProperty: String
init(s: String) {
myProperty = s
}
}
func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
return lhs.myProperty == rhs.myProperty
}
let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")
spClass1 === spClass2 // false
print("\(spClass1)")
spClass1 !== spClass2 // true
print("\(spClass2)")
خروجی :
main.SampleClass
main.SampleClass
Properties
زبان سوئیفت 4 ویژگی هایی را برای کلاس ، شمارش یا structure برای مرتبط کردن مقادیر فراهم می کند.
ویژگی ها را می توان بیشتر به properties ذخیره شده و properties محاسبه شده طبقه بندی کرد.
تفاوت بین properties ذخیره شده و properties محاسبه شده به شرح زیر است :
Stored Property | Computed Property |
---|---|
مقادیر ثابت و متغیر را به عنوان نمونه ذخیره کنید | به جای ذخیره کردن مقدار ، یک مقدار را محاسبه کنید |
ارائه شده توسط کلاس ها و structures | ارائه شده توسط کلاس ها ، enumerations و structures |
هر دو ویژگی ذخیره شده و محاسبه شده با نوع نمونه مرتبط هستند.
هنگامی که ویژگی ها با مقادیر نوع آن مرتبط می شوند ، به عنوان “Type Properties” تعریف می شود.
خواص ذخیره شده و محاسبه شده معمولاً با نمونه هایی از یک نوع خاص مرتبط هستند.
با این حال، ویژگی ها را می توان با خود نوع نیز مرتبط کرد.
چنین ویژگی هایی به عنوان خصوصیات نوع شناخته می شوند.
از ناظران اموال نیز استفاده می شود
Stored Properties
سوئیفت مفهوم Stored Property را برای ذخیره نمونه های ثابت و متغیر معرفی می کند.
ویژگی های ذخیره شده ثابت ها با کلمه کلیدی “let” و ویژگی های ذخیره شده متغیرها با کلمه کلیدی “var” تعریف می شوند.
در طول تعریف، ویژگی Stored “مقدار پیش فرض” را ارائه می دهد.
در طول Initialization، کاربر می تواند مقادیر اولیه را مقداردهی اولیه کرده و تغییر دهد.
struct Number {
var digits: Int
let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
خروجی :
67
3.1415
خط زیر را در کد بالا در نظر بگیرید :
let pi = 3.1415
در اینجا، متغیر pi به عنوان یک مقدار property ذخیره شده با نمونه pi = 3.1415 مقداردهی اولیه می شود.
بنابراین، هر زمان که نمونه ارجاع شود ، مقدار 3.1415 را به تنهایی حفظ می کند.
روش دیگر برای ذخیره property ، داشتن constant structures است.
بنابراین کل نمونه structures به عنوان “Stored Properties of Constants” در نظر گرفته می شود.
struct Number {
var digits: Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
آرایه initial که باید برای icecream مرتب شود به عنوان “Swift 4” و “great” داده شده است.
تابع مرتب سازی آرایه به عنوان نوع داده رشته ای و نوع برگشتی آن به عنوان Boolean ذکر می شود.
هر دو رشته با هم مقایسه و به ترتیب صعودی مرتب شده و در یک آرایه جدید ذخیره می شوند.
اگر مرتبسازی با موفقیت انجام شود ، تابع مقدار واقعی را برمیگرداند در غیر این صورت false را برمیگرداند.
سینتکس Closure expression از موارد زیر ، استفاده می کند :
- پارامترهای ثابت
- پارامترهای متغیر
- پارامترهای inout
Closure expression از مقادیر پیش فرض پشتیبانی نمی کند.
پارامترهای Variadic و Tuples نیز می توانند به عنوان انواع پارامترها و انواع برگشتی استفاده شوند.
struct Number {
var digits: Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
خروجی :
error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7
بهجای اینکه «number» را مجدداً به 8.7 مقداردهی کنید ، یک پیغام خطا نشان میدهد که «number» ثابت اعلام شده است.
Lazy Stored Propert
Swift 4 یک property منعطف به نام “Lazy Stored Property” را ارائه می دهد که در آن زمانی که متغیر برای اولین بار مقداردهی اولیه می شود، مقادیر اولیه را محاسبه نمی کند. |
مادیفایر ‘lazy’ قبل از اعلان متغیر استفاده می شود تا آن را به عنوان یک lazy stored property داشته باشیم.
از Lazy Properties استفاده می شود :
- برای به تاخیر انداختن ایجاد ابجکت
- هنگامی که Properties به سایر بخشهای یک کلاس وابسته است ، که هنوز شناخته نشدهاند
class sample {
lazy var no = number() // `var` declaration is required.
}
class number {
var name = "Swift 4"
}
var firstsample = sample()
print(firstsample.no.name)
خروجی :
Swift 4
متغیرهای نمونه
در Objective C، خواص Stored نیز دارای متغیرهای نمونه برای اهداف پشتیبان برای ذخیره مقادیر اعلام شده در ویژگی ذخیره شده است.
سوئیفت 4 هر دوی این مفاهیم را در یک اعلان “stored property” ادغام می کند.
به جای داشتن یک متغیر نمونه متناظر و مقدار پشتیبان ، “stored property” حاوی تمام اطلاعات یکپارچه تعریف شده در یک مکان واحد در مورد property متغیرها با نام variable ، نوع داده و عملکردهای مدیریت حافظه است.
ویژگی های محاسبه شده
خواص محاسبه شده به جای ذخیره مقادیر ، یک گیرنده و یک تنظیم کننده اختیاری برای بازیابی و تنظیم سایر properties و مقادیر به صورت غیر مستقیم ارائه می کند.
class sample {
var no1 = 0.0, no2 = 0.0
var length = 300.0, breadth = 150.0
var middle: (Double, Double) {
get {
return (length / 2, breadth / 2)
}
set(axis){
no1 = axis.0 - (length / 2)
no2 = axis.1 - (breadth / 2)
}
}
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
خروجی :
(150.0, 75.0)
-150.0
-65.0
هنگامی که یک property محاسبه شده مقدار جدید را تعریف نشده باقی می گذارد ، مقدار پیش فرض برای آن متغیر خاص تنظیم می شود.
property های محاسبه شده به عنوان property های read-only .
یک property نوع read-only در property محاسبه شده به عنوان یک property با getter اما بدون setter تعریف می شود.
همیشه برای برگرداندن یک مقدار استفاده می شود.
متغیرها بیشتر از طریق یک “.” قابل دسترسی هستند.
اما نمی توان آن را به مقدار دیگری تنظیم کرد.
class film {
var head = ""
var duration = 0.0
var metaInfo: [String:String] {
return [
"head": self.head,
"duration":"\(self.duration)"
]
}
}
var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
خروجی :
Swift 4 Properties
3.09
Computed Properties به عنوان Property Observers
در سوئیفت 4 برای مشاهده و پاسخ به مقادیر دارایی از Property Observers استفاده می شود.
هر زمانی که مقادیر Property تنظیم می شود ، property observers فراخوانی می شوند.
به جز lazy stored properties ، میتوانیم property observers را با متد «overriding» به پراپرتی«inherited» اضافه کنیم.
Property Observers را می توان با هر دو تعریف کرد.
- قبل از ذخیره مقدار ، willset
- پس از ذخیره مقدار جدید ، didset
هنگامی که یک Property در یک مقدار اولیه تنظیم می شود ، willset و didset observers نمی توانند فراخوانی شوند.
class Samplepgm {
var counter: Int = 0 {
willSet(newTotal){
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
خروجی :
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Querying و Setting Properties
دقیقاً مانند Type properties ، نیز Type properties به شکلی queried می شوند و با ‘.’ تنظیم می شوند.
به جای اشاره به instance ، صرفاً بر روی type صرف کنید.
struct StudMarks {
static let markCount = 97
static var totalCount = 0
var InternalMarks: Int = 0 {
didSet {
if InternalMarks > StudMarks.markCount {
InternalMarks = StudMarks.markCount
}
if InternalMarks > StudMarks.totalCount {
StudMarks.totalCount = InternalMarks
}
}
}
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)
خروجی :
97
87
Methods
در زبان سوئیفت 4 به توابع مرتبط با انواع خاص به عنوان Methods گفته می شود.
در Objective C از کلاس ها برای تعریف متدها استفاده می شود، در حالی که زبان Swift 4 انعطاف پذیری کاربر را برای داشتن متدهایی برای کلاس ها، Structures و Enumerations فراهم می کند.
Instance Methods
در زبان سوئیفت 4، کلاسها ، Structures و نمونههای Enumeration از طریق متدهای نمونه قابل دسترسی هستند.
متد های نمونه عملکردی :
- برای دسترسی و اصلاح instance properties
- عملکرد مربوط به نیاز نمونه
متد Instance را می توان در داخل پرانتزهای {} نوشت.
دسترسی implicit به متد ها و پراپتری های type instance دارد.
هنگامی که یک نمونه خاص از type فراخوانی می شود ، به آن نمونه خاص دسترسی پیدا می کند.
func funcname(Parameters) -> returntype {
Statement1
Statement2
---
Statement N
return parameters
}
مثال :
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
pri.result()
خروجی :
Result is: 880
Result is: 850
محاسبات کلاس دو متد نمونه ، را تعریف می کند :
() init برای جمع کردن دو عدد a و b و ذخیره آن در نتیجه “res” تعریف شده است.
() tot برای تفریق ‘res’ از مقدار ‘c’ استفاده می شود.
در نهایت برای چاپ روش های محاسباتی با مقادیر a و b فراخوانی می شود.
متدهای نمونه با “.” قابل دسترسی هستند.
Local و External Parameter Names
توابع Swift 4 هر دو اعلان local و global را برای متغیرهایشان توصیف می کند.
به طور مشابه، قراردادهای نامگذاری Swift 4 Methods نیز شبیه به هدف C است.
اما ویژگی های اعلانهای نام پارامترهای local و global برای توابع و متد ها متفاوت است.
اولین پارامتر در سوئیفت 4 با نام های اضافه به عنوان “with”، “for” و “by” برای دسترسی آسان به قراردادهای نامگذاری ارجاع می شود.
Swift 4 با اعلام نام پارامتر اول به عنوان نام پارامترهای local و نام پارامترهای باقیمانده به عنوان نام پارامترهای global ، انعطاف پذیری در متد ها را فراهم می کند.
در اینجا ‘no1’ توسط متدهای سوئیفت 4 به عنوان نام پارامترهای local اعلام می شود.
‘no2’ برای global declarations استفاده می شود و از طریق برنامه قابل دسترسی است.
class division {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 / no2
print(count)
}
}
let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)
خروجی :
600
320
3666
نام پارامتر خارجی با علامت # و _
حتی اگر متد های Swift 4 نام پارامترهای اول را برای اعلانهای loacal ارائه میکنند ، کاربر این امکان را دارد که نام پارامترها را از اعلانهای loacal به global تغییر دهد.
این را می توان با پیشوند نماد ‘#’ با نام پارامتر اول انجام داد.
با انجام این کار، پارامتر اول را می توان به صورت global در سراسر ماژول ها دسترسی داشت.
هنگامی که کاربر نیاز به دسترسی به نام پارامترهای بعدی با یک نام خارجی دارد ، نام متد ها با کمک نماد ‘_’ overridden می شود.
class multiplication {
var count: Int = 0
func incrementBy(no1: Int, no2: Int) {
count = no1 * no2
print(count)
}
}
let counter = multiplication()
counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)
خروجی :
2400
500
45000
ویژگی های خود در روش ها
متدها دارای یک implicit property هستند که به عنوان “self” برای همه type instances تعریف شده آن شناخته می شود.
پراپرتی”Self” برای ارجاع نمونه های فعلی برای متد های تعریف شده آن استفاده می شود.
class calculations {
let a: Int
let b: Int
let res: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
res = a + b
print("Inside Self Block: \(res)")
}
func tot(c: Int) -> Int {
return res - c
}
func result() {
print("Result is: \(tot(c: 20))")
print("Result is: \(tot(c: 50))")
}
}
let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)
pri.result()
sum.result()
خروجی :
Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450
اصلاح انواع ارزش از Instance Methods
در سوئیفت 4 ، structures و enumerations زبان متعلق به انواع مقادیر هستند که با متد های instance آن قابل تغییر نیستند.
با این حال، زبان سوئیفت 4 انعطافپذیری را برای اصلاح انواع مقادیر با رفتار “mutating” فراهم میکند.
Mutate هر گونه تغییری را در متدهای instance ایجاد می کند و پس از اجرای متد به شکل اصلی باز می گردد.
همچنین توسط ویژگی ‘self’ نمونه جدیدی برای implicit function آن ایجاد می شود و پس از اجرای آن جایگزین متد موجود می شود.
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
length *= res
breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)
خروجی :
9
15
270
450
81000
135000
Self Property برای متد Mutating
متدهای Mutating همراه با ویژگی “self” یک نمونه جدید به متد تعریف شده اختصاص می دهد.
struct area {
var length = 1
var breadth = 1
func area() -> Int {
return length * breadth
}
mutating func scaleBy(res: Int) {
self.length *= res
self.breadth *= res
print(length)
print(breadth)
}
}
var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)
خروجی :
39
65
Type Methods
هنگامی که یک نمونه خاص از یک متد فراخوانی می شود،
به عنوان یک Instance method نامیده می شود.
و زمانی که متد یک نوع خاص از یک متد را فراخوانی میکند ، آن را «Type Methods» مینامند.
Instance method برای «classes» با کلمه کلیدی «func» و structures و متدهای enumerations type با کلمه کلیدی «static» قبل از کلمه کلیدی «func» تعریف میشوند.
متدهای Type فراخوانی می شوند و با ‘.’ قابل دسترسی هستند.
سینتکسی که در آن به جای فراخوانی یک نمونه خاص، کل متد فراخوانی می شود.
class Math {
class func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
struct absno {
static func abs(number: Int) -> Int {
if number < 0 {
return (-number)
} else {
return number
}
}
}
let no = Math.abs(number: -35)
let num = absno.abs(number: -5)
print(no)
print(num)
خروجی :
35
5
Subscripts
دسترسی به عناصر یک مجموعه، sequence و لیست در کلاس ها ، Structures و Enumerations با کمک subscripts انجام می شود.
این زیرنویس ها برای ذخیره و بازیابی مقادیر با کمک index استفاده می شوند.
عناصر آرایه با کمک someArray[index] قابل دسترسی هستند و عناصر عضو بعدی آن در یک Dictionary instance می توانند به عنوان someDicitonary[key] دسترسی داشته باشند.
برای یک single type ، قطعا subscript ها می توانند از یک تا چند اعلان متفاوت باشند.
میتوانیم از subscript مناسب برای اضافه بار کردن نوع مقدار index ارسال شده به subscript استفاده کنیم.
subscript ها نیز با توجه به نیازهای کاربران برای اعلان نوع داده ورودی آنها از یک بعد تا چند بعد متغیر است.
سینتکس Subscript Declaration و استفاده از آن
Subscript ها نیز از همان سینتکس propertie های محاسبه شده پیروی می کنند.
برای querying type instances ، در واقع Subscript ها در داخل یک براکت مربع به دنبال نام instance نوشته می شوند.
سینتکس Subscript از همان ساختار سینتکسی پیروی می کند که از «instance method» و سینتکس «computed property» پیروی می کند.
کلمه کلیدی ‘subscript’ برای تعریف Subscript ها استفاده می شود و کاربر می تواند پارامترهای منفرد یا چندگانه را با نوع بازگشت آنها مشخص کند.
Subscript ها می توانند ویژگی های read-write یا read-only داشته باشند و instance ها با کمک ویژگی های ‘getter’ و ‘setter’ مانند ویژگی های محاسبه شده ذخیره و بازیابی می شوند.
subscript(index: Int) −> Int {
get {
// used for subscript value declarations
}
set(newValue) {
// definitions are written here
}
}
مثال :
struct subexample {
let decrementer: Int
subscript(index: Int) -> Int {
return decrementer / index
}
}
let division = subexample(decrementer: 100)
print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")
خروجی :
The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times
مثال ۲ :
class daysofaweek {
private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "saturday"]
subscript(index: Int) -> String {
get {
return days[index]
}
set(newValue) {
self.days[index] = newValue
}
}
}
var p = daysofaweek()
print(p[0])
print(p[1])
print(p[2])
print(p[3])
خروجی :
Sunday
Monday
Tuesday
Wednesday
آپشن ها در Subscript
Subscript پارامترهای ورودی یک تا چندگانه را می گیرد و این پارامترهای ورودی نیز به هر نوع داده ای تعلق دارند.
آنها همچنین می توانند از پارامترهای متغیر و متغیر استفاده کنند.
Subscript ها نمی توانند مقادیر پارامترهای پیش فرض را ارائه دهند یا از پارامترهای ورودی استفاده کنند.
تعریف subscript های متعدد به عنوان “subscript overloading” نامیده می شود که در آن یک کلاس یا ساختار می تواند تعاریف چندگانه را در صورت لزوم ارائه دهد.
این subscript های چندگانه بر اساس انواع مقادیری که در داخل پرانتزهای subscript اعلام شده اند braces می شوند.
struct Matrix {
let rows: Int, columns: Int
var print: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
print = Array(count: rows * columns, repeatedValue: 0.0)
}
subscript(row: Int, column: Int) -> Double {
get {
return print[(row * columns) + column]
}
set {
print[(row * columns) + column] = newValue
}
}
}
var mat = Matrix(rows: 3, columns: 3)
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
print("\(mat[0,0])")
خروجی :
1.0
subscript از اعلان های یک پارامتر به چند پارامتر برای انواع داده های مناسب پشتیبانی می کند.
این برنامه ساختار “Matrix” را به عنوان یک ماتریس آرایه 2 * 2 بعدی برای ذخیره انواع داده “Double” اعلام می کند.
پارامتر ماتریس با انواع داده های عدد صحیح برای اعلام سطرها و ستون ها وارد می شود.
نمونه جدید برای ماتریس با ارسال تعداد سطر و ستون به مقداردهی اولیه همانطور که در زیر نشان داده شده است ایجاد می شود.
var mat = Matrix(rows: 3, columns: 3)
مقادیر ماتریس را می توان با ارسال مقادیر سطر و ستون به subscript تعریف کرد که با کاما مطابق شکل زیر از هم جدا می شوند.
mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0
وراثت
به طور کلی یک کلاس می تواند متدها ، ویژگ ی ها و عملکردها را از کلاس دیگری به ارث ببرد.
کلاس ها را می توان بیشتر به زیر کلاس (sub class) و سوپر کلاس طبقه بندی کرد.
Sub Class : وقتی یک کلاس خواص ، متدها و توابع را از کلاس دیگری به ارث می برد ، به عنوان زیر کلاس نامیده می شود.
Super Class : کلاسی که حاوی ویژگی ها ، متدها و توابع برای ارث بردن کلاس های دیگر از خودش است به عنوان یک سوپر کلاس نامیده می شود.
کلاسهای سوئیفت 4 حاوی سوپرکلاس هستند که فراخوانی میکنند و به متدها ، ویژگیها ، توابع و متدهای overriding دسترسی دارند.
همچنین ، property observers نیز برای افزودن یک property و اصلاح متد های property ذخیرهشده یا محاسبهشده استفاده میشوند.
Base Class
کلاسی که متدها، خصوصیات یا توابع را از کلاس دیگری به ارث نمی برد، «Base Class» نامیده می شود.
class StudDetails {
var stname: String!
var mark1: Int!
var mark2: Int!
var mark3: Int!
init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
self.stname = stname
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76
print(stname)
print(mark1)
print(mark2)
print(mark3)
خروجی :
Swift 4
98
89
76
کلاس با نام کلاس StudDetails به عنوان یک کلاس پایه (base class) در اینجا تعریف می شود که برای نام دانش آموزان استفاده می شود و سه موضوع به عنوان mark1، mark2 و mark3 علامت گذاری می شوند.
کلمه کلیدی “let” برای مقداردهی اولیه برای کلاس پایه استفاده می شود و مقدار کلاس پایه با کمک تابع “print” در playground نمایش داده می شود.
Subclass
عمل پایه گذاری یک کلاس جدید بر روی یک کلاس موجود به عنوان ‘Subclass’ تعریف می شود.
زیر کلاس خصوصیات ، متد ها و عملکردهای کلاس پایه خود را به ارث می برد.
برای تعریف یک کلاس فرعی “:” قبل از نام کلاس پایه (base class) استفاده می شود.
class StudDetails {
var mark1: Int;
var mark2: Int;
init(stm1:Int, results stm2:Int) {
mark1 = stm1;
mark2 = stm2;
}
func print() {
print("Mark1:\(mark1), Mark2:\(mark2)")
}
}
class display : StudDetails {
init() {
super.init(stm1: 93, results: 89)
}
}
let marksobtained = display()
marksobtained.print()
خروجی :
Mark1:93, Mark2:89
کلاس ‘StudDetails’ به عنوان یک سوپر کلاس تعریف می شود که در آن نمرات دانش آموز اعلام می شود و زیر کلاس ‘display’ برای به ارث بردن علائم از سوپر کلاس آن استفاده می شود.
Sub class مارک های دانشآموز را تعریف میکند و متد () print را برای نمایش mark دانشآموز فراخوانی میکند.
Overriding
دسترسی به super class instance ، type methods، instance، type propertie و زیر کلاس subscripts مفهوم overriding را ارائه می دهد.
کلمه کلیدی ‘override’ برای نادیده گرفتن متد های اعلام شده در سوپرکلاس استفاده می شود.
دسترسی به متد ها ، propertie ها و Subscript های کلاس Super
کلمه کلیدی “super” به عنوان پیشوند برای دسترسی به متدها ، propertie ها و subscript های اعلام شده در کلاس فوق استفاده می شود.
Overriding | Access to methods,properties and subscripts |
Methods | () super.somemethod |
Properties | () super.someProperty |
Subscripts | super[someIndex] |
Methods Overriding
type methods را میتوان با کلمه کلیدی ‘override’ به روشهای تعریفشده در زیر کلاس ما لغو کرد.
در اینجا () print در زیر کلاس برای دسترسی به خاصیت type ذکر شده در () super class print .
همچنین نمونه جدیدی از سوپر کلاس () cricket به عنوان ‘cricinstance’ ایجاد می شود.
class cricket {
func print() {
print("Welcome to Swift 4 Super Class")
}
}
class tennis: cricket {
override func print() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.print()
let tennisinstance = tennis()
tennisinstance.print()
خروجی :
Welcome to Swift Super Class
Welcome to Swift Sub Class
Property Overriding
میتوانید یک نمونه یا property کلاس ارثی را نادیده بگیرید تا گیرنده (getter ) و تنظیمکننده (setter ) سفارشی خود را برای آن property ارائه دهید ، یا property observers را اضافه کنید تا وقتی مقدار property اصلی تغییر میکند ، property اصلی را فعال کنید.
Overriding Property Getters و Setter
سوئیفت 4 به کاربر اجازه می دهد تا getter و setter سفارشی را برای لغو inherited property ، چه یک پراپرتی stored یا computed ، ارائه دهد.
زیر کلاس نام و نوع property ارثی را نمی داند.
بنابراین ضروری است که کاربر باید در زیر کلاس، نام و نوع overriding property در سوپر کلاس را مشخص کند.
این را می توان به دو روش انجام داد :
هنگامی که setter برای overriding property استفاده می شود ، کاربر باید getter را نیز تعریف کند.
زمانی که نمیخواهیم inherited property getter را تغییر دهیم ، میتوانیم به سادگی مقدار ارثی را با دستور “super.someProperty” به کلاس super ارسال کنیم.
class Circle {
var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
خروجی :
Radius of rectangle for 25.0 is now overridden as 3
Property نهایی برای جلوگیری از Overriding
زمانی که کاربر نیازی به دسترسی دیگران به متدها ، propertie ها یا subscripts سوپر کلاس نداشته باشد، سوئیفت propertie ای با نام final را برای جلوگیری از overriding معرفی میکند.
هنگامی که پراپرتی”final ” اعلام شد ، subscript ها اجازه نمیدهند که متدهای سوپر کلاس ، propertie هعا و subscript های آن لغو شوند.
هیچ شرطی برای داشتن پراپرتی”final ” در “super class” وجود ندارد.
هنگامی که final property اعلام می شود، کاربر برای ایجاد زیر کلاس های بیشتر محدود می شود.
final class Circle {
final var radius = 12.5
var area: String {
return "of rectangle for \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " is now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
class Square: Rectangle {
override var radius: Double {
didSet {
print = Int(radius/5.0)+1
}
}
}
let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")
خروجی :
:14:18: error: var overrides a 'final' var
override var area: String {
^
:7:9: note: overridden declaration is here
var area: String {
^
:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
:25:14: error: var overrides a 'final' var
override var radius: Double {
^
:6:14: note: overridden declaration is here
final var radius = 12.5
مهرسا امینی
برنامه نویس ، انیماتور ، سئوکار
زندگي در حين گرفتن چيزهايي از تو موقعيت هاي جديدي را مي بخشد