Generic (جنریک پروگرامنگ) — Swift کا ایک میکانزم ہے جو پارامیٹرائزڈ ٹائپ
اہم نکات
Generic (جنریک ٹائپ) — Swift میں ایک سنٹیکٹیکل تعمیر ہے جو ٹائپ پارامیٹرائزیشن کے ساتھ لچیلا، دوبارہ استعمال کے قابل کوڈ لکھنے کی اجازت دیتا ہے۔ ایک ٹھوس ٹائپ کے بجائے، زاویے بریکٹس میں ایک پلیس ہولڈر لکھا جاتا ہے — عام طور پر
Generics کے بغیر، آپ کو ہر ٹائپ کے لیے علیحدہ فنکشنز لکھنے ہونگے: swapInts، swapStrings، swapDates۔ ایک generic swap فنکشن ایک اعلان سے تینوں متغیرات کو بدل دیتا ہے۔ یہ دوہراو کم کرتا ہے، پڑھنے میں آسانی پیدا کرتا ہے اور کوڈ کاپی کرتے وقت غلطیوں کے امکانات کو کم کرتا ہے۔
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
Swift کامپائلر generic کے ہر ٹھوس استعمال کے لیے مخصوصی کوڈ تیار کرتا ہے۔ اس کا مطلب ہے کہ generic فنکشن swapValues
جنریک فنکشنز وہ فنکشنز ہیں جو ایک یا زائد ٹائپ پارامیٹرز کو قبول کرتے ہیں۔ ٹائپ پارامیٹرز فنکشن کے نام کے بعد زاویے بریکٹس میں متعین کیے جاتے ہیں:
ایک فنکشن میں متعدد generic پارامیٹر ہو سکتے ہیں۔ مثال کے طور پر، findKey
func findKey<K: Hashable, V>(
for value: V,
in dictionary: [K: V]
) -> K? where V: Equatable {
for (key, dictValue) in dictionary {
if dictValue == value {
return key
}
}
return nil
}
پابندیاں K: Hashable اور where V: Equatable اس بات کی ضمانت دیتی ہیں کہ findKey صرف ایسے فرہنگ کے ساتھ بلایا جا سکتا ہے جس کی کنجیاں ہیشیبل اور اقدار ایکواٹیبل ہوں۔ ایسی پابندیاں بیروکریسی نہیں بلکھ ضرورت ہیں: Hashable کے بغیر آپ کنجی کی تلاش کو انڈیکس نہیں کر سکتے، Equatable کے بغیر آپ value کو dictValue سے موازنہ نہیں کر سکتے۔
where — Swift کا ایک کلمہ کلیدی ہے جو generic پارامیٹرز پر اضافی پابندیاں عائد کرتا ہے۔ زاویے بریکٹس (
where کا جملہ فنکشن یا ٹائپ کے دستخت کے بعد، کھولے ہونے والے تیرے سے پہلے لکھا جاتا ہے۔ where میں آپ متعین کر سکتے ہیں کہ T: Comparable & Hashable (ایک ساتھ دو پروٹیکلز کی تعمیل) یا T.U == Int (ایک associated type کو ٹھوس کرنا)۔
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
}
extension Container where Item: Comparable {
func isSorted() -> Bool {
// Implementation available only if Item: Comparable
return true
}
}
where کے ساتھ ایکسٹنشن صرف ان ٹائپس کے لیے میتھڈ شامل کرتا ہے جو شرط کو پورا کرتے ہیں۔ Container
Associated Types (منسلک اقسام) — ایک پروٹیکل کو اعلان کے مرحلے پر ٹھوس ٹائپ متعین کیئے بغیر جنریک بنانے کا ایک طریقہ ہے۔
where کا استعمال کرکے آپ مختلف پروٹیکلز کے associated types کے درمیان تعلقات قائم کر سکتے ہیں۔ مثال کے طور پر، آپ یہ تقاضا کر سکتے ہیں کہ ایک پروٹیکل کا Item دوسرے کے Iterator.Element سے ملتا ہو۔ یہ کامپائلر سطح پر ٹائپ مطابقت کی ضمانت دیتا ہے۔
protocol StackProtocol {
associatedtype Element
mutating func push(_ item: Element)
mutating func pop() -> Element?
}
struct IntStack: StackProtocol {
typealias Element = Int
private var items: [Int] = []
mutating func push(_ item: Int) { items.append(item) }
mutating func pop() -> Int? { items.popLast() }
}
IntStack typealias استعمال کرکے Element کو Int کے طور پر ٹھوس کرتا ہے۔ کامپائلر تصدیق کرتا ہے کہ پروٹیکل کی تمام ضرورتیں اس ٹائپ کے ساتھ پوری ہوتی ہیں۔ associated types کے بغیر، آپ کو ایک generic پروٹیکل کے ساتھ StackProtocol
Generic ایکسٹنشنز اضافی پابندیوں کے ساتھ ایک generic ٹائپ میں میتھڈ شامل کرنے کی اجازت دیتے ہیں۔ یہ مشروطی مطابقت کا پیٹرن ہے، جس میں ایک ٹائپ صرف مخصوص شرائط میں ہی فنکشنالٹی حاصل کرتا ہے۔ سب سکرپٹس بھی generic ہو سکتے ہیں۔
ایک سب سکرپٹ generic ہو سکتا ہے: یہ زاویے بریکٹس میں generic پارامیٹرز کو قبول کرتا ہے۔ یہ ایسے مجموعوں تک محفوظ رسائی کے لیے مفید ہے جہاں انڈیکس مختلف اقسام کا ہو سکتا ہے۔
extension Array where Element: Numeric {
func sum() -> Element {
return reduce(0, +)
}
}
extension Array {
subscript<Indices: Sequence>(indices: Indices) -> [Element]
where Indices.Element == Int {
return indices.map { self[$0] }
}
}
یہ تعمیر طاقتور کمپوزیشن فراہم کرتی ہے: sum میتھڈ صرف عددی ایرے پر ظاہر ہوتا ہے، اور صلحیتی انڈیکس کے ساتھ سب سکرپٹ عددی انڈیکس کے کسی بھی سیکونس کے ساتھ کام کرتا ہے۔ کامپائلر where کی شرائط کے بنیاد پر ان ارکان کی نمایاں کا انتظام کرتا ہے۔
غلطیاں generic کا استعمال کرتے وقت عام طور پر غلط پابندیوں یا اس جگہ generic استعمال کرنے کی کوشش سے متعلق ہوتی ہیں جہاں ٹھوس ٹائپ کی ضرورت ہوتی ہے۔ آئیے تین عام مناظر پر نظر ڈالیں جن کا ڈیولپرز کو سامنا کرنا پڑتا ہے۔
جہاں ٹھوس ٹائپ کافی ہو وہاں generic پارامیٹرز شامل کرنا ایک انٹی پیٹرن ہے۔ اگر ایک فنکشن ہمیشہ String کے ساتھ کام کرتا ہے، تو اسے
اس بات کو متعین کیئے بغیر کہ میتھڈ موجود ہے، generic پارامیٹر پر ایک میتھڈ کو کال کرنا ایک غلطی ہے۔
// ❌ Error: value has no count method
func countElements<T>>(value: T) -> Int { value.count }
// ✅ Works: T: Collection guarantees count exists
func countElements<T: Collection>(value: T) -> Int { value.count }
غلطی واضح ہے: generic
اکثر پوچے جانے والے سوالات
Generic کوڈ لکھنے کا ایک طریقہ ہے جو Int، String اور دیگر اقسام کے لیے ایک ہی منطق کو دوہرائے بغیر کسی بھی ٹائپ کے ساتھ کام کرتا ہے۔ ایک ٹھوس ٹائپ کے بجائے، ایک پلیس ہولڈر
Generic کامپائل ٹائم پر ٹھوس ٹائپ کی معلومات محفوظ رکھتا ہے، جو کامپائلر کو ٹائپس چیک کرنے اور بہترین کوڈ تیار کرنے کی اجازت دیتا ہے۔ Any ٹائپ میٹانا ہے: کوئی بھی قیمت پاس کی جا سکتی ہے، لیکن ٹائپ خو جاتا ہے اور کاسٹنگ (as?) کی ضرورت ہوتی ہے۔
زاویے بریکٹس میں T: SomeProtocol سنٹیکس یا الگ ضابطہ where where T: SomeProtocol استعمال کریں۔ پابندیاں اس بات کی ضمانت دیتی ہیں کہ generic پارامیٹر مخصوص میتھڈز اور خوصیات کو سپورٹ کرتا ہے۔
Associated Type (associatedtype) ایک پروٹیکل کے اندر ایک ٹائپ کے لیے ایک پلیس ہولڈر ہے۔ پروٹیکل ایک ٹھوس ٹائپ متعین نہیں کرتا بلکھ ایک associatedtype کا اعلان کرتا ہے، جو نفاذ میں ٹھوس ہوتا ہے: Array کا Element، Dictionary کا Key اور Value۔
Swift generic کوڈ کو ہر ٹھوس ٹائپ کے لیے مخصوصی ورشنز میں کامپائل کرتا ہے۔ عملی طور پر، Int کے لیے ایک generic فنکشن Int کے لیے هاتھ سے لکھے گئے فنکشن سے آہستہ نہیں ہے۔ تجرید کا کوئی اورہیڈ نہیں ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں