Throw এবং Throws প্রোগ্রামিং ভাষায় ব্যতিক্রম থ্রো এবং ঘোষণা করার পদ্ধতি। throw অপারেটর একটি ফাংশনের স্বাভাবিক নির্বাহ বাধাগ্রস্ত করে এবং ত্রুটি অবজেক্টটি কল স্ট্যাকের উপরে প্রেরণ করে। ফাংশন সিগনেচারে throws কীওয়ার্ড কলকারী পক্ষকে ত্রুটির সম্ভাবনা সম্পর্কে সতর্ক করে, কোডকে পূর্বানুমানযোগ্য করে তোলে। Kotlin ডকুমেন্টেশন (2026) অনুযায়ী, Kotlin-এ throw একটি এক্সপ্রেশন, নির্দেশ নয়, যা এটি when-ব্লক এবং এলভিস অপারেটরের ভিতরে ব্যবহার করার অনুমতি দেয়।
মূল বিষয়
Throw একটি অপারেটর যা প্রোগ্রাম নির্বাহের বিন্দুতে একটি ব্যতিক্রম তৈরি করে। যখন throw এর সম্মুখীন হয়, বর্তমান নির্বাহ প্রবাহ অবিলম্বে বাধাগ্রস্ত হয় এবং নিয়ন্ত্রণ কল স্ট্যাকের নিকটতম catch হ্যান্ডলারের কাছে স্থানান্তরিত হয়। যদি কোনো হ্যান্ডলার না পাওয়া যায়, অ্যাপ্লিকেশনটি ক্র্যাশ হয়। মোবাইল ডেভেলপমেন্টে throw ব্যবহার করা হয় সেই ত্রুটিগুলি সংকেত দিতে যা বিমূর্ততার বর্তমান স্তরে হ্যান্ডল করা যায় না — যেমন, অবৈধ সার্ভার প্রতিক্রিয়া, নেটওয়ার্কের অনুপস্থিতি বা ভুল আর্গুমেন্ট।
Throws — একটি ফাংশন সিগনেচারে একটি মডিফায়ার (প্রধানত Swift-এ) যা ঘোষণা করে যে ফাংশনটি একটি ত্রুটি থ্রো করতে পারে। এটি Swift-এ checked ত্রুটি প্রক্রিয়ার অংশ: কলকারী পক্ষ do-catch, try?, try! এর মাধ্যমে ত্রুটি হ্যান্ডল করতে বা আরও প্রসারের জন্য নিজের ফাংশনকে throws হিসেবে চিহ্নিত করতে বাধ্য। Kotlin এবং Java-তেও throws বিদ্যমান, কিন্তু Kotlin এটিকে অপ্রয়োজনীয় মনে করে — Kotlin-এ সব ব্যতিক্রম unchecked, অর্থাৎ সিনট্যাক্টিক বাধ্যতা ছাড়া সেগুলি হ্যান্ডল না-ও হতে পারে। Apple Swift ডকুমেন্টেশন (2026) অনুযায়ী, Swift-এ throws ফাংশন টাইপে ত্রুটির সম্ভাবনা স্পষ্টভাবে ঘোষণা করার একমাত্র উপায়, যা ডেভেলপারের জন্য API চুক্তি স্বচ্ছ করে তোলে।
throw এবং throws-এর মধ্যে পার্থক্য মৌলিক: throw একটি ক্রিয়া (রানটাইমে ব্যতিক্রম থ্রো করা), throws একটি ঘোষণা (কম্পাইল-টাইম চুক্তি)। 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-ও সমর্থন করে — উচ্চ-ক্রম ফাংশনের জন্য একটি মডিফায়ার যা throws ক্লোজার গ্রহণ করে এবং তার ত্রুটি প্রসারিত করে। rethrows মানে হল ফাংশনটি কেবল তখনই ত্রুটি থ্রো করে যদি পাস করা ক্লোজারটি একটি থ্রো করে — ফাংশনটি নিজে কোনো ত্রুটি উৎপন্ন করে না।
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-ক্লোজার সহ ব্যবহার
let parsed = try mapValues(jsonStrings) { str in
let data = Data(str.utf8)
return try JSONDecoder().decode(Item.self, from: data)
}
rethrows mapValues ফাংশনকে নমনীয় করে তোলে: এটি throws-ক্লোজার এবং সাধারণ উভয়ই গ্রহণ করে। যদি throws-ক্লোজার পাস করা হয়, mapValues কলের জন্য try প্রয়োজন; যদি সাধারণ হয়, try প্রয়োজন নেই। এটি rethrows-কে Swift স্ট্যান্ডার্ড লাইব্রেরির map, filter, reduce-এর মতো উচ্চ-ক্রম ফাংশনের জন্য আদর্শ করে তোলে। Apple-এর সুপারিশ: যেসব API throws-ক্লোজার গ্রহণ করে এবং ত্রুটির একমাত্র উৎস সেই ক্লোজার, সেগুলির জন্য rethrows ব্যবহার করুন। যদি ফাংশন নিজস্ব ত্রুটি থ্রো করতে পারে, 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-ক্লজ |
| 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? কনফিগারেশন ফাইল পড়ার জন্য ব্যবহার করা হয়েছে — যদি ফাইল অনুপস্থিত বা দূষিত হয়, অ্যাপ্লিকেশন ক্র্যাশ হওয়ার পরিবর্তে ডিফল্ট মান ব্যবহার করে। try do-catch-এ নেটওয়ার্ক অনুরোধের জন্য ব্যবহার করা হয়েছে যেখানে ত্রুটি প্রত্যাশিত এবং ব্যবহারকারীর প্রতিক্রিয়া প্রয়োজন। সুপারিশ: প্রোডাকশন কোডে try! এড়িয়ে চলুন — শুধুমাত্র বিল্ড সময়ে যাচাইকৃত ধ্রুবক ডেটার জন্য এটি ব্যবহার করুন।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Throw একটি অপারেটর যা প্রোগ্রাম নির্বাহের সময় একটি ত্রুটি থ্রো করে, প্রবাহ বাধাগ্রস্ত করে। Throws একটি ফাংশন সিগনেচার মডিফায়ার যা ঘোষণা করে যে ফাংশনটি একটি ত্রুটি থ্রো করতে পারে। throws ছাড়া একটি ফাংশন throw ব্যবহার করতে পারে না। Throws একটি কম্পাইল-টাইম চুক্তি, throw একটি রানটাইম ক্রিয়া।
Kotlin unchecked ব্যতিক্রমের দর্শন অনুসরণ করে: সব ব্যতিক্রম সিনট্যাক্টিক বাধ্যতা ছাড়া অনিয়ন্ত্রিত থাকতে পারে। Kotlin ডেভেলপাররা মনে করেন যে Java-তে throws অত্যধিক try-catch ব্লক এবং খালি catch-এর মাধ্যমে checked ব্যতিক্রম উপেক্ষা করার দিকে নিয়ে যায়। Kotlin-এর Nothing টাইপ throw-কে এক্সপ্রেশন হিসেবে ব্যবহার করার অনুমতি দেয়, throws-কে আরও নমনীয় পদ্ধতিতে প্রতিস্থাপন করে।
try! কেবল তখনই গ্রহণযোগ্য যখন আপনি সম্পূর্ণরূপে নিশ্চিত যে ত্রুটি অসম্ভব: বান্ডেল থেকে স্পষ্টতই বৈধ JSON, ধ্রুবক ডেটা, সঠিক URL স্কিম। প্রোডাকশন কোডে, try! একটি ব্যতিক্রম, নিয়ম নয়। try? ফলব্যাক মান সহ ঐচ্ছিক পরিস্থিতির জন্য পছন্দনীয়, try do-catch-এর সাথে বাধ্যতামূলক ত্রুটি হ্যান্ডলিংয়ের জন্য।
Rethrows ফাংশনগুলির জন্য একটি মডিফায়ার যা throws-ক্লোজার গ্রহণ করে। rethrows সহ একটি ফাংশন কেবল তখনই ত্রুটি থ্রো করে যদি পাস করা ক্লোজারটি একটি থ্রো করে। এটি উচ্চ-ক্রম ফাংশন (map, filter) কে কলকারী পক্ষে try বাধ্য না করে throws এবং non-throws উভয় ক্লোজারের সাথে কাজ করার অনুমতি দেয়।
হ্যাঁ, catch-এর ভিতরে আপনি ত্রুটিকে একটি ভিন্ন টাইপে মোড়ক করে বা প্রসঙ্গ যোগ করে স্ট্যাকের উপরে প্রসারিত করতে throw ব্যবহার করতে পারেন। একে error chaining বা rethrow বলা হয়। Swift-এ, catch-এর ভিতরে আরেকটি throw যথেষ্ট; Kotlin-এ, catch ব্লকের ভিতরে throw। finally ব্লক নিয়ন্ত্রণ আরও প্রেরণের আগে নির্বাহিত হয়।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন