paint-brush
Swift init()، ایک بار اور سب کے لیےکی طرف سے@kfamyn
نئی تاریخ

Swift init()، ایک بار اور سب کے لیے

کی طرف سے Kiryl Famin19m2025/03/21
Read on Terminal Reader

بہت لمبا؛ پڑھنے کے لئے

یہ مضمون سوئفٹ انیشیلائزرز کے لیے ضروری ہر چیز کا احاطہ کرتا ہے: ممبر کے مطابق، نامزد، سہولت، سہولت اوور رائیڈ؛ ضروری استعمال کے معاملات؛ پیرامیٹر لیس UIView() انیشیلائزر؛ کمپائلر مدد؛ ناکام init، enum init اور مزید۔
featured image - Swift init()، ایک بار اور سب کے لیے
Kiryl Famin HackerNoon profile picture
0-item
1-item

تعارف

ہیلو! میرا نام کیرل فامین ہے، اور میں ایک iOS ڈویلپر ہوں۔


آج، میں سوئفٹ میں ابتداء کے طور پر اس طرح کے ایک سادہ موضوع کا اچھی طرح سے جائزہ لینا چاہتا ہوں۔ اس کی ظاہری سادگی کے باوجود، بعض اوقات اس موضوع کی مکمل تفہیم کی کمی مایوس کن غلطیوں کا باعث بنتی ہے جسے کوئی شخص تفصیلات میں جانے کے بغیر جلدی ٹھیک کرنا چاہتا ہے۔


اس آرٹیکل میں، ہم ابتدا کرنے والوں سے متعلق ہر چیز کا احاطہ کریں گے، بشمول:


  • کسٹم کی وضاحت کرتے ہوئے ڈھانچے کے ممبر وائز انیشیلائزر کو کیسے برقرار رکھا جائے۔

  • کلاسوں میں ابتدائی لکھنا ہمیشہ کیوں ضروری نہیں ہوتا ہے۔

  • کیوں super.init کو کال کرنے کی ہمیشہ ایک مقررہ ابتدائی میں ضرورت نہیں ہوتی ہے۔

  • super.init کال کرنے سے پہلے ذیلی طبقے کے تمام فیلڈز کو کیوں پاپولیشن کرنا ضروری ہے۔

  • ذیلی طبقات میں کم سے کم اوور رائیڈ کے ساتھ تمام پیرنٹ انیشیلائزرز تک کیسے رسائی حاصل کی جائے۔

  • جب بالکل ایک required ابتداء کی ضرورت ہوتی ہے۔

  • UIView.init() کو ہمیشہ پیرامیٹرز کے بغیر کیوں کہا جاتا ہے، لیکن init(frame:) اور init(coder:) اوور رائیڈ کیا جاتا ہے


...اور مزید لیکن آئیے اسے قدم بہ قدم چلتے ہیں۔

مندرجات کا جدول

بنیادی باتیں

ڈھانچے

  • ممبر کے مطابق ابتدا کرنے والا
  • اختیاری
  • var بمقابلہ let
  • ممبر وائز انیشیلائزر کو برقرار رکھنا

کلاسز

  • نامزد ابتدائی کنندہ
  • سہولت شروع کرنے والا
  • سپرکلاس کی سہولت شروع کرنے والا برقرار رکھنا
  • اوور رائیڈز کی تعداد کو کم سے کم کرنا
  • کمپائلر کی مدد
  • required ابتدائی کنندہ: generics، protocols، Self() , final
  • UIView() بغیر پیرامیٹرز کے

معزز تذکرہ

  • ناکام init
  • اینومس

خلاصہ

متعلقہ لنکس

بنیادی باتیں

ایپل کی گائیڈ دی سوئفٹ پروگرامنگ لینگویج (6) (جو ویسے بھی، ابتدا کرنے والوں کے لیے حیرت انگیز طور پر تفصیلی ہے) کہتی ہے:


ابتداء ایک کلاس، ڈھانچے، یا استعمال کے لیے شمار کی مثال تیار کرنے کا عمل ہے۔ اس عمل میں اس مثال پر ہر ذخیرہ شدہ پراپرٹی کے لیے ایک ابتدائی قدر کا تعین کرنا اور کسی دوسرے سیٹ اپ یا ابتداء کو انجام دینا شامل ہے جو نئی مثال کے استعمال کے لیے تیار ہونے سے پہلے درکار ہے۔


آپ ابتداء کے اس عمل کو شروع کرنے والے کی وضاحت کرتے ہوئے لاگو کرتے ہیں، جو کہ خاص طریقوں کی طرح ہیں جنہیں کسی خاص قسم کی نئی مثال بنانے کے لیے کہا جا سکتا ہے۔ Objective-C انیشیلائزرز کے برعکس، سوئفٹ انیشیلائزرز کوئی قدر واپس نہیں کرتے ہیں۔ ان کا بنیادی کردار یہ یقینی بنانا ہے کہ کسی قسم کی نئی مثالیں پہلی بار استعمال ہونے سے پہلے صحیح طریقے سے شروع کی جائیں۔


ٹھیک ہے، مجھے لگتا ہے کہ مجھے یہاں کچھ بھی شامل کرنے کی ضرورت نہیں ہے۔

ڈھانچے

آئیے سٹرکچر انیشیلائزرز پر بحث کرتے ہوئے شروع کریں۔ یہ بہت آسان ہے کیونکہ کوئی وراثت نہیں ہے، لیکن پھر بھی کچھ اصول ہیں جن کے بارے میں آپ کو جاننا چاہیے۔

ممبر کے مطابق ابتدا کرنے والا

آئیے ایک سادہ ساخت لکھتے ہیں:

 struct BankAccount { let amount: Double let isBlocked: Bool } let bankAccount = BankAccount(amount: 735, isBlocked: Bool)


نوٹ کریں کہ ہم واضح طور پر ابتدائیہ کا اعلان کیے بغیر ساخت کو شروع کرنے کے قابل تھے۔ ایسا اس لیے ہوتا ہے کیونکہ ڈھانچے کو کمپائلر کے ذریعے تیار کردہ ممبر وار انیشیلائزر ملتا ہے۔ یہ صرف ڈھانچے کے لیے کام کرتا ہے۔


Refactor → Generate memberwise ابتداء کو منتخب کرکے، آپ دیکھ سکتے ہیں کہ یہ کیسا لگتا ہے:


ایکس کوڈ میں ممبر وائز انیشیلائزر تیار کرنا


 init(amount: Double, isBlocked: Bool) { self.amount = amount self.isBlocked = isBlocked }


دستخط سے، یہ دیکھنا آسان ہے کہ تمام پیرامیٹرز کے لیے اقدار فراہم کرنے میں ناکامی کے نتیجے میں تالیف کی غلطی ہو جائے گی:

 let bankAccount = BankAccount(amount: 735) // ❌ Missing argument for parameter 'isBlocked' in call


تاہم، اگر آپ مطلوبہ دلائل کی تعداد کو کم کرنا چاہتے ہیں، تو آپ اپنی مرضی کے مطابق ابتدا کرنے والے کی وضاحت کر سکتے ہیں:

 init(amount: Double, isBlocked: Bool = false) { self.amount = amount isBlocked = isBlocked } let bankAccount = BankAccount(amount: 735) // ✅


نوٹ کریں کہ اگر isBlocked آباد نہیں کیا گیا ہے، تو اس کے نتیجے میں تالیف کی خرابی ہو گی کیونکہ تمام ڈھانچے کی خصوصیات کو انیشیلائزر میں آباد کرنا ضروری ہے ۔

اختیاری، var بمقابلہ let

واحد صورت جہاں کسی فیلڈ کو واضح طور پر آباد کرنے کی ضرورت نہیں ہے جب یہ اختیاری ( ? ) متغیر ( var ) ہو۔ ایسی صورتوں میں، فیلڈ ڈیفالٹ ہو جائے گا nil :

 struct BankAccount { let amount: Double var isBlocked: Bool? init(amount: Double) { self.amount = amount } } let bankAccount = BankAccount(amount: 735) // ✅


تاہم، اگر ہم اس معاملے میں ممبر وائز انیشیلائزر کو استعمال کرنے کی کوشش کرتے ہیں، تو ہمیں ایک تالیف کی خرابی ملے گی:

 let bankAccount = BankAccount( amount: 735, isBlocked: false ) // ❌ Extra argument 'isBlocked' in call

ممبر وائز انیشیلائزر کو برقرار رکھنا

ایسا اس لیے ہوتا ہے کہ کسٹم انیشیلائزر کا اعلان کرنے سے ممبر وائز انیشیلائزر ہٹ جاتا ہے۔ واضح طور پر اس کی وضاحت کرنا اب بھی ممکن ہے، لیکن یہ خود بخود دستیاب نہیں ہوگا۔


تاہم، ممبر وائز انیشیلائزر کو برقرار رکھنے کے لیے ایک چھوٹی سی چال ہے: extension میں کسٹم انیشیلائزر کا اعلان کریں۔

 struct BankAccount { let amount: Double var isBlocked: Bool? } extension BankAccount { init(amount: Double) { self.amount = amount } } let barclaysBankAccount = BankAccount(amount: 735) // ✅ let revolutBankAccount = BankAccount(amount: 812, isBlocked: false) // ✅ print(barclaysBankAccount.isBlocked) // nil print(barclaysBankAccount.isBlocked) // false


ڈھانچے کا خلاصہ

  • تمام فیلڈز کو ایک انیشیلائزر میں آباد کیا جانا چاہیے۔
  • اختیاری var فیلڈز ڈیفالٹ سے nil
  • سٹرکچرز کو ممبر کے مطابق ایک مفت انیشیلائزر ملتا ہے۔
  • ممبر وائز انیشیلائزر غائب ہو جاتا ہے اگر حسب ضرورت انیشیلائزر کا اعلان کیا جاتا ہے۔
  • ڈھانچے کے ممبر وائز انیشیلائزر کو برقرار رکھنے کے لیے، extension میں اپنی مرضی کے مطابق کی وضاحت کریں۔

کلاسز

نامزد ابتدائی کنندہ

کلاس کے لیے پرائمری انیشیلائزر نامزد انیشیلائزر ہے۔ یہ دو مقاصد کو پورا کرتا ہے:

  1. اس بات کو یقینی بناتا ہے کہ تمام فیلڈز آباد ہیں۔
  2. اگر کلاس وراثت میں ملی ہے، تو اسے سپر کلاس انیشیلائزر کہتے ہیں۔
 class Animal { var name: String init(name: String) { self.name = name } } class Dog: Animal { var breed: String var name: String init(breed: String, name: String) { self.breed = breed super.init(name: name) } }


super.init کال کرنے سے پہلے تمام فیلڈز کو آباد کرنا ضروری ہے ۔ اس کی وجہ یہ ہے کہ سپر کلاس انیشیلائزر ذیلی طبقے کے ذریعے اوور رائیڈ کردہ طریقوں کو کال کر سکتا ہے، جو غیر آباد ذیلی طبقے کی خصوصیات تک رسائی حاصل کر سکتے ہیں۔

 class Animal { var age: Int init(age: Int) { self.age = age getInfo() } func getInfo() { print("Age: ", age) } } class Dog: Animal { var breed: String init(breed: String, age: Int) { self.breed = breed // imagine we haven't done this super.init(age: age) } override func getInfo() { print("Age: ", age, ", breed: ", breed) } }


اس طرح، اگر ہم نے self.breed = breed سیٹ نہ کیا ہوتا تو ہمیں رن ٹائم غلطی کا سامنا کرنا پڑتا کیونکہ Animal انیشیلائزر نے Dog کلاس سے اوور رائیڈڈ getInfo() طریقہ کو کال کیا ہوتا۔ یہ طریقہ breed جائیداد تک رسائی حاصل کرنے کی کوشش کرتا ہے، جو ابھی تک آباد نہیں ہوگی۔


ڈھانچے کے برعکس، کلاسوں کو رکنیت کے لحاظ سے ایک مضمر ابتدائیہ موصول نہیں ہوتا ہے۔ اگر غیر شروع شدہ خصوصیات ہیں تو، ایک تالیف کی خرابی واقع ہوتی ہے:

 class Animal { // ❌ Class 'Animal' has no initializers var age: Int }
 class Animal { // ✅ var age: Int = 0 }
 class Animal { // ✅ var age: Int? }
 class Animal { } // ✅

سہولت شروع کرنے والا

کلاسوں میں سہولت شروع کرنے والا بھی ہو سکتا ہے۔ نامزد انیشیلائزرز کے برعکس، وہ شروع سے کوئی چیز نہیں بناتے ہیں بلکہ دوسرے انیشیلائزرز کی منطق کو دوبارہ استعمال کر کے ابتدا کے عمل کو آسان بناتے ہیں۔

 class Rectangle { var width: Double var height: Double init(width: Double, height: Double) { self.width = width self.height = height } convenience init(side: Double) { self.init(width: side, height: side) // uses a designated initializer of self } }


سہولت شروع کرنے والے یا تو نامزد انیشیلائزرز یا دیگر سہولت انیشیلائزرز کو کال کر سکتے ہیں۔ بالآخر، ایک نامزد ابتدائی کنندہ کو ہمیشہ بلایا جائے گا۔

سہولت، نامزد اور سپر کلاس انیشیلائزرز


سہولت شروع کرنے والے ہمیشہ افقی (self.init) جاتے ہیں، اور نامزد ابتدائی عمودی (super.init) جاتے ہیں۔

سپرکلاس کی سہولت کی ابتداء کو برقرار رکھنا

جیسے ہی کوئی ذیلی طبقہ نئی خصوصیات کا اعلان کرتا ہے، یہ سپرکلاس کے تمام سہولتوں کے آغاز تک رسائی کھو دیتا ہے۔

 class Animal { var age: Int var name: String init(age: Int, name: String) { self.age = age self.name = name } convenience init(age: Int) { self.init(age: age, name: "Default") } convenience init(name: String) { self.init(age: 0, name: name) } } class Dog: Animal { var breed: String init(age: Int, name: String, breed: String) { self.breed = breed super.init(age: age, name: name) } } let dog = Dog(age: 3) // ❌ Missing arguments for parameters 'breed', 'name' in call 


موجودہ ابتدائی درجہ بندی، صرف ایک init کا واضح طور پر اعلان کیا گیا ہے۔


اسے سپر کلاس کے تمام نامزد ابتدائیوں کو اوور رائیڈ کر کے ٹھیک کیا جا سکتا ہے۔

 class Dog: Animal { // ... override init(age: Int, name: String) { self.breed = "Mixed" super.init(age: age, name: name) } } let dog = Dog(age: 3) // ✅ 


سہولت شروع کرنے والوں کو اب دوبارہ حاصل کر لیا گیا ہے، لیکن دو ابتدا کاروں کا واضح طور پر اعلان کیا گیا ہے۔


یہ دیکھنا آسان ہے کہ، اس طرح، اگلے ذیلی طبقے میں ایک سہولت انیشیئلائزر استعمال کرنے کے لیے، آپ کو دو انیشیلائزرز کو اوور رائڈ کرنے کی ضرورت ہے۔

 class GuideDog: Dog { var isTrained: Bool override init(age: Int, name: String) { self.isTrained = false super.init(age: age, name: name) } override init(age: Int, name: String, breed: String) { self.isTrained = false super.init(age: age, name: name, breed: breed) } init(age: Int, name: String, breed: String, isTrained: Bool) { self.isTrained = isTrained super.init(age: age, name: name, breed: breed) } } let dog = GuideDog(age: 3) // ✅ 


سہولت شروع کرنے والوں کو دوبارہ حاصل کر لیا گیا ہے، لیکن گائیڈ ڈاگ واضح طور پر تین ابتدائیوں کی وضاحت کرتا ہے


اوور رائیڈز کی تعداد کو کم سے کم کرنا

تاہم، سہولت اوور رائیڈ انیشیلائزر کا استعمال کر کے اس سے بچا جا سکتا ہے۔

 class Dog: Animal { var breed: String convenience override init(age: Int, name: String) { self.init(age: age, name: name, breed: "Mixed") // self, not super } init(age: Int, name: String, breed: String) { self.breed = breed super.init(age: age, name: name) } } class GuideDog: Dog { var isTrained: Bool // override init(age: Int, name: String) { // self.isTrained = false // // super.init(age: age, name: name, breed: "Mixed") // } convenience override init(age: Int, name: String, breed: String) { self.init(age: age, name: name, breed: breed, isTrained: false) // self, not super } init(age: Int, name: String, breed: String, isTrained: Bool) { self.isTrained = isTrained super.init(age: age, name: name, breed: breed) } } let dog = GuideDog(age: 3) // ✅ 


دو اینیمل کی سہولت شروع کرنے والے دوبارہ حاصل کیے گئے ہیں، کتے کی سہولت شروع کی گئی ہے (عمر:، نام:) دوبارہ حاصل کی گئی ہے اور صرف دو GuideDog کے ابتدائی طور پر واضح طور پر بیان کیے گئے ہیں


اب ہمارے پاس ہر ذیلی طبقے میں صرف 2 واضح طور پر مخصوص ابتدائیہ ہیں۔

غور کریں کہ کس طرح سہولت کو اوور رائیڈ انیشیلائزر super.init کی بجائے self نامزد init کہتے ہیں۔

اس چال کی وضاحت سوئفٹ ان ڈیپتھ کے باب 5 میں Tjeerd کی طرف سے 't Veen میں کی گئی ہے، ایک کتاب جس کی میں انتہائی سفارش کرتا ہوں۔

انٹرمیڈیٹ کا خلاصہ

  • ایک نامزد انیشیلائزر اس بات کو یقینی بناتا ہے کہ تمام پراپرٹیز آباد ہیں اور super.init() کو کال کرتا ہے۔
  • ایک سہولت انیشیلائزر ایک نامزد انیشیلائزر کو کال کرکے ابتدا کو آسان بناتا ہے۔
  • ایک سہولت شروع کرنے والا ذیلی طبقات کے لیے دستیاب نہیں ہو جاتا ہے اگر وہ نئی خصوصیات کا اعلان کرتے ہیں۔
  • ایک سپر کلاس کے سہولت انیشیلائزر کو بحال کرنے کے لیے، اس کے تمام نامزد کردہ انیشیلائزرز کو اوور رائڈ کرنا ضروری ہے۔
  • اوور رائیڈز کی تعداد کو کم کرنے کے لیے، سہولت اوور رائیڈ انیشیلائزر استعمال کیا جا سکتا ہے۔

کمپائلر کی مدد

ہم پہلے ہی بحث کر چکے ہیں کہ اگر ذیلی طبقہ نئے پیرامیٹرز کو متعارف نہیں کرواتا ہے، تو یہ خود بخود سپر کلاس کے تمام ابتدائیوں کو وراثت میں لے جاتا ہے۔

 class Base { let value: Int init() { value = 0 } init(value: Int) { self.value = value } } class Subclass: Base { } let subclass = Subclass() // ✅ let subclass = Subclass(value: 3) // ✅


تاہم، ایک اور اہم نکتہ ہے: اگر سپرکلاس میں صرف ایک نامزد ابتدائیہ ہے اور یہ پیرامیٹر لیس ہے ( init() بغیر دلائل کے، تو پھر ذیلی کلاس میں واضح طور پر اعلان کردہ ابتدا کاروں کو super.init() کو کال کرنے کی ضرورت نہیں ہے۔ اس صورت میں، سوئفٹ کمپائلر بغیر کسی دلیل کے دستیاب super.init() پر کال داخل کرتا ہے ۔

 class Base { init() { } } class Subclass: Base { let secondValue: Int init(secondValue: Int) { self.secondValue = secondValue // ✅ without explicit super.init() } }


کوڈ مرتب کرتا ہے کیونکہ super.init() واضح طور پر کہا جاتا ہے۔ یہ مندرجہ ذیل مثالوں میں سے کچھ کے لیے اہم ہے۔

درکار ہے۔

ایک required انیشیلائزر ان تمام صورتوں میں استعمال کیا جاتا ہے جہاں ایک ذیلی کلاس میں بیس کلاس کی طرح ایک ہی انیشیلائزر ہونا ضروری ہے۔ اسے super.init() کو بھی کال کرنا چاہیے۔ ذیل میں ایسی مثالیں دی گئی ہیں جہاں ایک required ابتداء ضروری ہے۔

جنرک

ایک عام قسم پر init کال کرنا صرف اسے ایک required init قرار دے کر ہی ممکن ہے۔

 class Base { } class Subclass: Base { } struct Factory<T: Base> { func initInstance() -> T { // ❌ Constructing an object of class T() // type 'T' with a metatype value } // must use a 'required' initializer }


یہ کوڈ مرتب نہیں ہوتا ہے کیونکہ Factory Base کے ذیلی طبقات کے بارے میں کچھ نہیں معلوم۔ اگرچہ اس خاص معاملے میں، Subclass میں پیرامیٹرز کے بغیر ایک init() ہے، تصور کریں کہ کیا اس نے ایک نیا فیلڈ متعارف کرایا ہے:

 class Subclass: Base { let value: Int init(value: Int) { self.value = value } }


یہاں، اس میں اب کوئی خالی init نہیں ہے، لہذا اسے required کے مطابق قرار دیا جانا چاہیے۔

 class Base { required init() { } } class Subclass: Base { } struct Factory<T: Base> { static func initInstance() -> T { // ✅ T() } } let subclass = Factory<Subclass>.initInstance()


نوٹ کریں کہ اگرچہ ہم نے واضح طور پر Subclass میں required init اعلان نہیں کیا، لیکن مرتب کرنے والے نے اسے ہمارے لیے تیار کیا۔ اس پر کمپائلر اسسٹنس میں تبادلہ خیال کیا گیا تھا۔ required init خود بخود وراثت میں ملا تھا اور اسے super.init() کہا جاتا تھا۔

 class Subclass: Base { required init() { super.init() } }

پروٹوکولز

پروٹوکول میں اعلان کردہ تمام ابتداء کی required :

 protocol Initable { init() } class InitableObject: Initable { init() { // ❌ Initializer requirement 'init()' can only // be satisfied by a 'required' initializer } // in non-final class 'InitableObject' }


ایک بار پھر، یہ ضروری ہے تاکہ کمپائلر اس بات کو یقینی بنائے کہ ذیلی کلاس پروٹوکول انیشیلائزر کو لاگو کرتا ہے۔ جیسا کہ ہم پہلے ہی جانتے ہیں، ایسا ہمیشہ نہیں ہوتا — اگر init required نہیں ہے، ذیلی طبقے کو اس کو اوور رائڈ کرنے کا پابند نہیں ہے اور وہ خود اپنے ابتدائی کنندہ کی وضاحت کر سکتا ہے۔

 class IntValue: InitableObject { let value: Int init(value: Int) { self.value = value } } let InitableType: Initable.Type = IntValue.self let initable: Initable = InitableType.init()


یقینا، درج ذیل کوڈ مرتب نہیں ہوگا کیونکہ Base.init() required نہیں ہے۔

 class InitableObject: Initable { required init() { } // ✅ } class IntValue: InitableObject { let value: Int required init() { self.value = 0 } init(value: Int) { self.value = value } }

خود()

اسی طرح کی صورتحال اس وقت ہوتی ہے جب Self() انیشیلائزر کو جامد طریقوں میں کال کرتے ہیں۔

 class Base { let value: Int init(value: Int) { self.value = value } static func instantiate() -> Self { Self(value: 3) // ❌ Constructing an object of class type 'Self' } // with a metatype value must use a 'required' initializer }


ہمیشہ کی طرح، مسئلہ وراثت میں ہے:

 class Subclass: BaseClass { let anotherValue: Int init(anotherValue: Int) { self.anotherValue = anotherValue } } let subclass = Subclass.instantiate() // ❌
 class BaseClass { let value: Int required init(value: Int) { // ✅ self.value = value } static func instantiate() -> Self { Self(value: 3) } }

required سے چھٹکارا حاصل کرنا: final

چونکہ required کا مقصد ذیلی طبقات میں ابتدائیہ کے نفاذ کو نافذ کرنا ہے، قدرتی طور پر، final مطلوبہ لفظ کا استعمال کرتے ہوئے وراثت پر پابندی لگانا required کے مطابق ابتدائیہ کو نشان زد کرنے کی ضرورت کو ختم کرتا ہے۔

 protocol Initable { init() } final class InitableObject: Initable { } // ✅
 protocol ValueInitable { init(value: Int) } final class ValueInitableObject: ValueInitable { init(value: Int) { } // ✅ }

انٹرمیڈیٹ کا خلاصہ

  • اگر ایک ذیلی کلاس نئے پیرامیٹرز کو متعارف نہیں کراتی ہے، تو یہ خود بخود اپنے سپرکلاس سے تمام ابتداء کو وراثت میں لے لیتا ہے۔
  • اگر سپرکلاس میں صرف init() پیرامیٹرز کے بغیر ہے، تو اسے سب کلاس انیشیلائزرز میں خود بخود کہا جاتا ہے۔
  • generics، protocols، اور Self() میں استعمال کے لیے ذیلی طبقات میں اس کی موجودگی کی ضمانت کے لیے ایک required ابتداء کار کی ضرورت ہے۔

UIView()

پیرامیٹرز کے بغیر UIView() انیشیلائزر کا مختصر تذکرہ، جو دستاویزات میں نہیں پایا جا سکتا لیکن ہر جگہ پراسرار طور پر استعمال ہوتا ہے۔


وجہ یہ ہے کہ UIView NSObject سے وراثت میں ملتا ہے، جس میں init() پیرامیٹرز کے بغیر ہوتا ہے۔ لہذا ، اس ابتداء کار کو UIView انٹرفیس میں واضح طور پر اعلان نہیں کیا گیا ہے، پھر بھی یہ دستیاب ہے:

 @available(iOS 2.0, *) @MainActor open class UIView : UIResponder, NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, UIFocusItemContainer, CALayerDelegate { open class var layerClass: AnyClass { get } public init(frame: CGRect) public init?(coder: NSCoder) open var isUserInteractionEnabled: Bool // no init()


تاہم، ہڈ کے نیچے، یہ انیشیلائزر init(frame:) کہتا ہے جب کوڈ میں شروع کیا جاتا ہے یا init(coder:) جب انٹرفیس بلڈر کے ذریعے شروع کیا جاتا ہے۔ ایسا اس لیے ہوتا ہے کیونکہ UIView NSObject.init() کا اپنا نفاذ فراہم کرتا ہے، جس کی تصدیق اس حقیقت سے کی جا سکتی ہے کہ method_getImplementation NSObject.init() اور UIView.init() کے لیے مختلف پتے واپس کرتا ہے۔

معزز تذکرہ

ناکام init

ایک ناکام init صرف ایک ہے جو اختیاری لوٹاتا ہے۔

 final class Failable { let positiveValue: Int init?(value: Int) { guard value > 0 else { return nil } positiveValue = value } }

اینوم

خام قیمت والے اینومس کو مفت init?(rawValue:)

 enum Direction: String { case north case west case south case east } let north = Direction(rawValue: "north")

آپ enums کے لیے اپنی مرضی کے مطابق init بھی بنا سکتے ہیں۔ تمام enum inits کو self تفویض کرنا ضروری ہے۔

 enum DeviceType { case phone case tablet init(screenWidth: Int) { self = screenWidth > 800 ? .tablet : .phone } }

حتمی خلاصہ

ہم نے Swift میں ابتدائیہ کے تمام ضروری پہلوؤں کا احاطہ کیا ہے:


  • انیشیلائزر میں، تمام فیلڈز کو پاپولڈ ہونا چاہیے۔

  • اختیاری var پراپرٹیز ڈیفالٹ سے nil ۔

  • سٹرکچرز کو ایک مفت ممبر وائز انیشیلائزر ملتا ہے۔

  • ممبر وائز انیشیلائزر غائب ہو جاتا ہے جب ایک کسٹم انیشیلائزر کی تعریف کی جاتی ہے۔

  • ایک نامزد انیشیلائزر یقینی بناتا ہے کہ تمام فیلڈز آباد ہیں اور super.init() کو کال کرتا ہے۔

  • ایک سہولت انیشیلائزر ایک نامزد انیشیلائزر کو کال کرکے ابتدا کو آسان بناتا ہے۔

  • سہولت شروع کرنے والے ہمیشہ افقی ہوتے ہیں ( self.init )، اور نامزد انیشیلائزر عمودی ہوتے ہیں ( super.init

  • ایک سہولت شروع کرنے والا ذیلی طبقات کے لیے دستیاب نہیں ہو جاتا ہے اگر وہ نئی خصوصیات کا اعلان کرتے ہیں۔

  • ایک سپر کلاس کے سہولت انیشیلائزر کو بحال کرنے کے لیے، اس کے تمام نامزد کردہ انیشیلائزرز کو اوور رائڈ کرنا ضروری ہے۔

  • اوور رائیڈز کی تعداد کو کم کرنے کے لیے، سہولت اوور رائیڈ انیشیلائزر استعمال کیا جا سکتا ہے۔

  • اگر ایک ذیلی کلاس نئے پیرامیٹرز کو متعارف نہیں کراتی ہے، تو یہ خود بخود اپنے سپرکلاس سے تمام ابتداء کو وراثت میں لے لیتا ہے۔

  • اگر سپر کلاس میں صرف init() پیرامیٹرز کے بغیر ہے، تو اسے خود بخود ذیلی کلاس انیشیلائزرز میں بلایا جاتا ہے۔

  • ایک مطلوبہ انیشیئلائزر generics، protocols، اور Self() میں استعمال کے لیے ذیلی طبقات میں اپنی موجودگی کو یقینی بناتا ہے۔

  • UIView.init() UIView.init(frame:) یا UIView.init(coder:) کال کرتا ہے۔

  • ایک ناکام شروع کرنے والا ایک اختیاری واپس کرتا ہے۔

  • خام قدر والے اینومس کو مفت init?(rawValue:) ۔

  • تمام enum ابتداء کرنے والوں کو self تفویض کرنا ہوگا۔


مجھے امید ہے کہ آپ نے اس مضمون میں کچھ مفید پایا۔ اگر کوئی چیز غیر واضح رہتی ہے یا آپ کو غلط معلوم ہوتا ہے، تو ٹیلیگرام پر مفت وضاحت کے لیے بلا جھجھک مجھ سے رابطہ کریں: @kfamyn ۔

متعلقہ لنکس

  1. سوئفٹ پروگرامنگ لینگویج (6) / ابتداء
  2. سوئفٹ ان ڈیپتھ بذریعہ Tjeerd in 't Veen
  3. ٹیلیگرام - @kfamyn