Throw اور Throws پروگرامنگ زبانوں میں استثناء پھینکنے اور اعلان کرنے کے طریقہ کار ہیں۔ throw آپریٹر کسی فنکشن کے عام عمل کو روکتا ہے اور خرابی آبجیکٹ کو کال اسٹیک میں اوپر بھیجتا ہے۔ فنکشن کے دستخط میں throws کی ورڈ کال کرنے والے فریق کو خرابی کے امکان سے آگاہ کرتی ہے، کوڈ کو پیش قیاسی بناتا ہے۔ Kotlin دستاویز (2026) کے مطابق، Kotlin میں throw ایک اظہار (expression) ہے، بیان (statement) نہیں، جو اسے when بلاکس اور ایلوس آپریٹر کے اندر استعمال کرنے کی اجازت دیتا ہے۔
اہم نکات
Throw ایک آپریٹر ہے جو پروگرام کے عمل کے مقام پر ایک استثناء پیدا کرتا ہے۔ جب throw کا سامنا ہوتا ہے، موجودہ عمل کا سلسلہ فوری طور پر روک دیا جاتا ہے اور کنٹرول کال اسٹیک میں قریب ترین catch ہینڈلر کو منتقل کر دیا جاتا ہے۔ اگر کوئی ہینڈلر نہ ملے تو ایپلیکیشن کریش ہو جاتی ہے۔ موبائل ڈویلپمنٹ میں throw کا استعمال ان خرابیوں کی اطلاع دینے کے لیے کیا جاتا ہے جنہیں تجرید کی موجودہ سطح پر ہینڈل نہیں کیا جا سکتا — مثال کے طور پر، غلط سرور جواب، نیٹ ورک کی عدم موجودگی یا غلط آرگیومینٹس۔
Throws — فنکشن کے دستخط میں ایک modifier (بنیادی طور پر Swift میں) جو اعلان کرتا ہے کہ فنکشن ایک خرابی پھینک سکتا ہے۔ یہ Swift میں checked خرابی کے طریقہ کار کا حصہ ہے: کال کرنے والا فریق do-catch، try?، try! کے ذریعے خرابی کو ہینڈل کرنے یا مزید پھیلانے کے لیے اپنے فنکشن کو throws کے طور پر نشان زد کرنے کا پابند ہے۔ Kotlin اور Java میں بھی throws موجود ہے، لیکن Kotlin اسے بے کار سمجھتا ہے — Kotlin میں تمام استثناء unchecked ہیں، یعنی نحوی جبر کے بغیر انہیں ہینڈل نہیں کیا جا سکتا۔ Apple Swift دستاویز (2026) کے مطابق، Swift میں throws فنکشن کی قسم میں خرابی کے امکان کو واضح طور پر اعلان کرنے کا واحد طریقہ ہے، جو ڈویلپر کے لیے API معاہدوں کو شفاف بناتا ہے۔
throw اور throws کے درمیان فرق بنیادی ہے: throw ایک عمل ہے (رن ٹائم پر استثناء پھینکنا)، throws ایک اعلان ہے (compile-time معاہدہ)۔ throws کے بغیر فنکشن throw استعمال نہیں کر سکتا — Swift کمپائلر ایک خرابی پیدا کرے گا۔ throws والا فنکشن throw استعمال نہیں کر سکتا — اس کی اجازت ہے لیکن بے معنی ہے۔ یہ علیحدگی throw/throws کو ایک طاقتور API ڈیزائن ٹول بناتی ہے، جہاں خرابی کا معاہدہ فنکشن کے کال سے پہلے اس کے دستخط میں نظر آتا ہے۔
Swift میں، throw آپریٹر Error پروٹوکول کو لاگو کرنے والی کسی بھی قسم کو قبول کرتا ہے۔ سب سے عام طور پر یہ مختلف اقسام کی خرابیوں کے لیے کیسز والا ایک enum ہے۔ Swift Java طرز کے checked استثناء کو سپورٹ نہیں کرتا — اس کے بجائے، فنکشن کی قسم throws سے نشان زد کی جاتی ہے اور ہینڈلنگ کال کرنے والے فریق کو سونپ دی جاتی ہے۔ یہ Swift میں throw کو زیادہ لچکدار بناتا ہے لیکن ڈویلپر کے لیے زیادہ ذمہ داری بھی۔
Error پروٹوکول کے مطابق کوئی بھی قسم throw کے ذریعے پھینکی جا سکتی ہے۔ ڈویلپر اکثر سادہ خرابیوں کے لیے منسلک اقدار کے بغیر enum یا سیاق و سباق دینے کے لیے منسلک اقدار کے ساتھ enum استعمال کرتے ہیں۔ Swift میں خرابی کا enum ہونا ضروری نہیں ہے — آپ Error کو لاگو کرنے والی struct یا class استعمال کر سکتے ہیں، لیکن ہینڈلر کی طرف exhaustive switch کی وجہ سے enum افضل ہے۔ کمپائلر چیک کرتا ہے کہ do-catch میں تمام کیسز ہینڈل کیے گئے ہیں۔
enum AuthError: Error {
case invalidCredentials
case tokenExpired
case accountLocked(remainingMinutes: Int)
}
func login(username: String, password: String) throws -> Session {
guard isValid(username) else {
throw AuthError.invalidCredentials
}
let response = try api.authenticate(username, password)
if response.isLocked {
throw AuthError.accountLocked(
remainingMinutes: response.lockDuration
)
}
return Session(token: response.token)
}
AuthError تین منظرنامے بیان کرتا ہے: غلط اسناد، میعاد ختم شدہ ٹوکن، اور remainingMinutes کی منسلک قیمت کے ساتھ مقفل اکاؤنٹ۔ login فنکشن throws کے طور پر اعلان کردہ ہے — کمپائلر اسے try کے ذریعے کال کرنے کا تقاضا کرتا ہے۔ فنکشن کے اندر، throw دو جگہوں پر استعمال ہوتا ہے: غلط صارف نام کے لیے اور مقفل اکاؤنٹ کے لیے۔ منسلک قیمت accountLocked صارف کو مخصوص ڈیٹا دینے کی اجازت دیتی ہے — لاک کھلنے سے پہلے کتنے منٹ انتظار کرنا ہے۔ یہ طریقہ لاک کی حالت چیک کرنے کے لیے علیحدہ API اینڈ پوائنٹس کی ضرورت کو ختم کرتا ہے۔
Kotlin میں throw Nothing قسم کا ایک اظہار ہے، بیان نہیں۔ اس کا مطلب ہے کہ throw کو اسائنمنٹ کے دائیں طرف، when اظہار کے اندر اور ایلوس آپریٹر ?: میں استعمال کیا جا سکتا ہے۔ Nothing قسم Kotlin میں تمام اقسام کا ایک خاص ذیلی قسم ہے، جو throw کو ان جگہوں پر استعمال کرنے کی اجازت دیتی ہے جہاں کسی بھی قسم کی قدر درکار ہو۔ کمپائلر سمجھتا ہے کہ throw کے بعد عمل جاری نہیں رہتا اور اس معاملے کے لیے کسی شاخ کی ضرورت نہیں ہے۔
Nothing Kotlin میں ایک منفرد قسم ہے جو تمام ممکنہ اقسام کا ذیلی قسم ہے۔ Nothing واپس کرنے والا فنکشن (مثال کے طور پر، TODO()) کبھی عام طور پر مکمل نہیں ہوتا — یا تو ہمیشہ ایک استثناء پھینکتا ہے یا لامتناہی لوپ میں چلا جاتا ہے۔ یہ throw کو ان جگہوں پر استعمال کے لیے قدرتی امیدوار بناتا ہے جہاں قدر درکار ہو: ایلوس آپریٹر، else کے بغیر when، متغیر کی ابتدا۔ اگر throw کسی when شاخ میں ہے، کمپائلر سمجھتا ہے کہ شاخ Nothing کی طرف لے جاتی ہے اور اس شاخ کے لیے return یا else کی ضرورت نہیں ہے۔
data class Config(val apiUrl: String, val timeoutSec: Int)
class ConfigParser {
fun parse(json: String): Config {
val obj = JSONObject(json)
val url = obj.optString("apiUrl")
?: throw IllegalArgumentException("apiUrl is required")
val timeout = obj.optInt("timeoutSec", 30)
return Config(url, timeout)
}
fun getErrorMessage(code: Int): String {
return when (code) {
404 -> "Not found"
500 -> "Server error"
else -> throw IllegalArgumentException("Unknown code: $code")
}
}
}
پہلی مثال میں، throw ایلوس آپریٹر ?: میں استعمال ہوا ہے: اگر JSON میں apiUrl فیلڈ موجود نہیں ہے، throw اظہار فوری طور پر عمل کو روکتا ہے اور IllegalArgumentException پھینکتا ہے۔ Nothing قسم کمپائلر کو دائیں جانب کی قسم String کے طور پر اخذ کرنے کی اجازت دیتی ہے (ایلوس String کی توقع کرتا ہے، throw کی قسم Nothing ہے، Nothing String کا ذیلی قسم ہے)۔ دوسری مثال میں، when اظہار کے اندر throw: اگر کوڈ کسی معروف کوڈ سے مطابقت نہیں رکھتا، ایک استثناء پھینکا جاتا ہے۔ کمپائلر سمجھتا ہے کہ throw کے بعد کوڈ ناقابل رسائی ہے، لہذا فنکشن کی واپسی کی قسم String کی خلاف ورزی نہیں ہوتی۔
Swift میں throws پیرامیٹر کی فہرست کے بعد اور واپسی کی قسم کے تیر سے پہلے متعین کیا جاتا ہے۔ throws والا فنکشن صرف do-catch کے اندر یا try? کے ساتھ دوسرے throws فنکشنز کو کال کر سکتا ہے۔ اگر throws فنکشن خرابی کو ہینڈل نہیں کرتا، تو وہ اسے کال کرنے والے فریق کو بھیج دیتا ہے۔ Swift rethrows کو بھی سپورٹ کرتا ہے — ایک modifier اعلیٰ ترتیب والے فنکشنز کے لیے جو throws closure قبول کرتے ہیں اور اس کی خرابی پھیلاتے ہیں۔ rethrows کا مطلب ہے کہ فنکشن صرف اس صورت میں خرابی پھینکتا ہے جب پاس کردہ closure نے ایک پھینکی ہو — فنکشن خود کوئی خرابی پیدا نہیں کرتا۔
func mapValues<T>(
_ array: [T],
transform: (T) throws -> U
) rethrows -> [U] {
var result = [U]()
for element in array {
result.append(try transform(element))
}
return result
}
// throws closure کے ساتھ استعمال
let parsed = try mapValues(jsonStrings) { str in
let data = Data(str.utf8)
return try JSONDecoder().decode(Item.self, from: data)
}
rethrows mapValues فنکشن کو لچکدار بناتا ہے: یہ throws closures اور عام دونوں کو قبول کرتا ہے۔ اگر throws closure پاس کیا جائے، mapValues کال try کی ضرورت ہے؛ اگر عام ہے، try کی ضرورت نہیں ہے۔ یہ rethrows کو Swift اسٹینڈرڈ لائبریری میں map، filter، reduce جیسے اعلیٰ ترتیب والے فنکشنز کے لیے مثالی بناتا ہے۔ Apple کی سفارش: ان API کے لیے rethrows استعمال کریں جو throws closures قبول کرتے ہیں اور خرابی کا واحد ذریعہ وہ closure ہے۔ اگر فنکشن اپنی خرابی پھینک سکتا ہے، throws استعمال کریں۔
Swift throws checked استثناء (جیسے Java میں) کے قریب ہے — پھینکی گئی خرابیاں دستخط میں اعلان کردہ ہوتی ہیں۔ Kotlin اور Dart unchecked استثناء استعمال کرتے ہیں — دستخط میں throws ضروری نہیں ہے۔ فرق بنیادی ہے: checked ڈویلپر کو خرابی ہینڈل کرنے پر مجبور کرتا ہے (محفوظ لیکن زیادہ تفصیلی)، unchecked آزادی دیتا ہے لیکن خرابی ہینڈل کرنا بھولنے کا خطرہ بڑھاتا ہے۔ Swift نے throws کے لیے checked منتخب کیا، Kotlin نے تمام استثناء کے لیے unchecked منتخب کیا۔ دونوں طریقوں کے فوائد ہیں: Swift زبان کی سطح پر زیادہ قابل اعتماد ہے، Kotlin زیادہ جامع اور فنکشنل تبدیلی کی زنجیروں میں آسان ہے۔
موبائل ایپلیکیشنز میں منظم خرابی ہینڈلنگ کے لیے، بنیادی Exception یا Error استعمال کرنے کے بجائے اپنی مرضی کی خرابی کی اقسام بنانے کی سفارش کی جاتی ہے۔ Swift میں اس کے لیے Error پروٹوکول کے ساتھ enum استعمال کیا جاتا ہے؛ Kotlin میں Throwable (یا Exception) سے وراثت پانے والی sealed class؛ Dart میں Exception سے وراثت پانے والی class۔ اپنی مرضی کی اقسام خرابیوں کو زمروں میں گروپ کرنے اور منسلک ڈیٹا دینے کی اجازت دیتی ہیں۔
| زبان | خرابی کی قسم | خصوصیت |
|---|---|---|
| Swift | enum: Error { ... } | منسلک اقدار، catch میں exhaustive switch |
| Kotlin | sealed class : Throwable() | فیلڈ والی خرابیوں کے لیے Data class، when اظہار |
| Dart | class implements Exception | Message فیلڈ، catch میں on clause |
| Java | class extends Exception | Checked بمقابلہ unchecked، دستخط میں لازمی throws |
اپنی مرضی کی خرابیاں ڈیزائن کرتے وقت، اصول پر عمل کریں: ایک خرابی — ایک منظرنامہ۔ مختلف وجوہات کو String message فلیگ والی ایک قسم میں مت جوڑیں — ہر منظرنامے کے لیے علیحدہ کیسز/ذیلی طبقات بنائیں۔ اس سے کال کرنے والا فریق سٹرنگ موازنہ کے بجائے پیٹرن میچنگ (when/switch) کے ذریعے ہر کیس کو ہینڈل کر سکے گا۔ Swift میں یہ exhaustive checking فراہم کرتا ہے — کمپائلر خبردار کرے گا اگر NetworkError enum کا کوئی کیس ہینڈل نہیں کیا گیا۔
sealed class NetworkError(val message: String) : Throwable(message) {
data class Timeout(val durationMs: Long) :
NetworkError("Request timed out after ${durationMs}ms")
data class HttpError(val code: Int, val body: String?) :
NetworkError("HTTP $code")
data class NoConnection(val cause: IOException) :
NetworkError("No internet connection")
}
Sealed class NetworkError Throwable (Kotlin میں معیاری استثناء کی قسم) سے وراثت پاتی ہے۔ ہر ذیلی طبقہ اپنے فیلڈز کے ساتھ ایک data class ہے: Timeout میں ملی سیکنڈ میں ٹائم آؤٹ کی مدت ہے، HttpError میں کوڈ اور جواب کا باڈی ہے، NoConnection میں اصلی IOException ہے۔ یہ ڈیزائن when کے ذریعے مکمل ملاپ کے ساتھ ہر خرابی کو ہینڈل کرنے کی اجازت دیتا ہے (جب آپ نیا ذیلی طبقہ شامل کرتے ہیں، کمپائلر تمام when اظہار کو اپ ڈیٹ کرنے پر مجبور کرے گا)۔
Swift throws فنکشنز کال کرنے کے تین طریقے فراہم کرتا ہے، ہر ایک اپنے حفاظتی معاہدے کے ساتھ۔ try معیاری طریقہ ہے: اسے do-catch کی ضرورت ہے یا throws فنکشن کے اندر ہونے کی ضرورت ہے۔ try? خرابی کو nil میں تبدیل کرتا ہے — نتیجہ اختیاری ہو جاتا ہے، خرابی پر nil لوٹاتا ہے، قسم T سے T? میں بدل جاتی ہے۔ try! — ہینڈلنگ کے بغیر لازمی عمل: اگر کوئی خرابی پھینکی جاتی ہے، ایپلیکیشن کریش ہو جاتی ہے۔ try! صرف اس وقت استعمال کریں جب آپ کو مکمل یقین ہو کہ خرابی ناممکن ہے (مثال کے طور پر، واضح طور پر درست ڈیٹا)۔
let configPath = Bundle.main.path(forResource: "config", ofType: "json")!
// try? — اختیاری نتیجہ
let data = try? Data(contentsOf: URL(fileURLWithPath: configPath))
let json = try? JSONSerialization.jsonObject(with: data ?? Data())
// try! — یقینی کامیابی (صرف جب یقین ہو)
let decoder = JSONDecoder()
let defaultConfig = try! decoder.decode(
Config.self,
from: Config.defaultJSON
)
// try — معیاری ہینڈلنگ
do {
let user = try fetchUser()
showUser(user)
} catch let error as NetworkError {
showRetryAlert(error.message)
}
مثال میں، try! ایپ بُنڈل میں شامل واضح طور پر درست JSON کے لیے استعمال ہوتا ہے — صحیح ریلیز کے ساتھ ڈی کوڈنگ کی خرابی ناممکن ہے۔ try? کنفیگریشن فائل پڑھنے کے لیے استعمال ہوتا ہے — اگر فائل غائب یا خراب ہے، ایپلیکیشن کریش ہونے کے بجائے ڈیفالٹ ویلیوز استعمال کرتی ہے۔ do-catch میں try نیٹ ورک کی درخواستوں کے لیے استعمال ہوتا ہے جہاں خرابی متوقع ہے اور صارف کے جواب کی ضرورت ہے۔ سفارش: پروڈکشن کوڈ میں try! سے پرہیز کریں — صرف بلڈ ٹائم پر تصدیق شدہ مستقل ڈیٹا کے لیے استعمال کریں۔
اکثر پوچھے گئے سوالات
Throw ایک آپریٹر ہے جو پروگرام کے عمل کے دوران خرابی پھینکتا ہے، بہاؤ کو روکتا ہے۔ Throws ایک فنکشن دستخط modifier ہے جو اعلان کرتا ہے کہ فنکشن خرابی پھینک سکتا ہے۔ throws کے بغیر فنکشن throw استعمال نہیں کر سکتا۔ Throws ایک compile-time معاہدہ ہے، throw ایک run-time عمل ہے۔
Kotlin unchecked استثناء کے فلسفے کی پیروی کرتا ہے: تمام استثناء نحوی جبر کے بغیر غیر ہینڈل رہ سکتے ہیں۔ Kotlin کے ڈویلپرز مانتے ہیں کہ Java میں throws ضرورت سے زیادہ try-catch بلاکس اور خالی catch کے ذریعے checked استثناء کو نظر انداز کرنے کا باعث بنتا ہے۔ Kotlin کا Nothing قسم throw کو اظہار کے طور پر استعمال کرنے کی اجازت دیتا ہے، throws کو زیادہ لچکدار طریقے سے تبدیل کرتا ہے۔
try! صرف اس وقت قابل قبول ہے جب آپ کو مکمل یقین ہو کہ خرابی ناممکن ہے: بنڈل سے واضح طور پر درست JSON، مستقل ڈیٹا، درست URL سکیما۔ پروڈکشن کوڈ میں، try! ایک استثناء ہے، اصول نہیں۔ try? فال بیک ویلیو کے ساتھ اختیاری منظرناموں کے لیے بہتر ہے، try do-catch کے ساتھ لازمی خرابی ہینڈلنگ کے لیے۔
Rethrows ان فنکشنز کے لیے ایک modifier ہے جو throws closure قبول کرتے ہیں۔ rethrows والا فنکشن صرف اس صورت میں خرابی پھینکتا ہے جب پاس کردہ closure نے ایک پھینکی ہو۔ یہ اعلیٰ ترتیب والے فنکشنز (map, filter) کو کال کرنے والے فریق پر try مجبور کیے بغیر throws اور non-throws دونوں closures کے ساتھ کام کرنے کی اجازت دیتا ہے۔
ہاں، catch کے اندر آپ خرابی کو مختلف قسم میں لپیٹ کر یا سیاق و سباق شامل کر کے اسٹیک میں اوپر پھیلانے کے لیے throw استعمال کر سکتے ہیں۔ اسے error chaining یا rethrow کہا جاتا ہے۔ Swift میں، catch کے اندر ایک اور throw کافی ہے؛ Kotlin میں، catch بلاک کے اندر throw۔ finally بلاک کنٹرول مزید منتقل کرنے سے پہلے عمل میں آتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں