Elvis Operator — یک عملگر دودویی است که اگر عملوند چپ null نباشد آن را برمیگرداند، در غیر این صورت عملوند راست را برمیگرداند. در Kotlin، Groovy و برخی زبانهای دیگر به صورت ?: نوشته میشود. بر اساس Kotlin Language Documentation, 2024، این عملگر بخشی از سیستم null-safety زبان است و به شما امکان میدهد ساختارهای شرطی را بدون کاهش خوانایی به یک خط کاهش دهید. برخلاف نوشتار کامل if-else، Elvis Operator بخش راست را فقط در صورت null بودن مقدار چپ محاسبه میکند که در استفاده از عبارات پرهزینه پیشفرض مزیت عملکردی ایجاد میکند.
نکات اصلی
Elvis Operator — یک عملگر دودویی است که به افتخار مدل موی الویس پریسلی نامگذاری شده است. نماد ?: از نظر بصری چهره خواننده را از نمای نیمرخ تداعی میکند: علامت سوال — چشم و ساقه مو، دو نقطه — دهان. عملگر دو عملوند میپذیرد: اگر اولی null نباشد — آن برگردانده میشود، در غیر این صورت دومی برگردانده میشود. این امکان جایگزینی ساختار کامل if-else با یک نوشتار کوتاه را فراهم میکند.
نام «Elvis Operator» در جامعه Kotlin و Groovy تثبیت شد و سپس به Xtend و سایر زبانهای JVM منتقل شد. در Swift و Dart ساختار مشابه nil-coalescing operator نامیده میشود، اما از نظر عملکردی یکسان است. تداعی بصری با الویس پریسلی به این عملگر کمک کرد تا به یکی از شناختهشدهترین نمادها در نحو زبانهای برنامهنویسی مدرن تبدیل شود.
Elvis Operator بخشی از سیستم null safety است که از NullPointerException (NPE) جلوگیری میکند. بر اساس تحقیقات JetBrains در سال 2023، NPE 28% از تمام استثناها را در کد تولیدی روی JVM تشکیل میدهد. استفاده از Elvis Operator در نقطه انتساب کاملاً NPE را حذف میکند و مقدار پیشفرض را تضمین میکند. در ترکیب با عملگر فراخوانی امن ?. یک زنجیره قابل اعتماد بدون هیچ بلوک if به دست میآید.
در Kotlin Elvis Operator به صورت ?: بین دو عبارت نوشته میشود. اگر عبارت چپ null نباشد — نتیجه برابر با چپ است، در غیر این صورت عبارت راست محاسبه میشود. عبارت راست تنبلانه محاسبه میشود — فقط در صورت null بودن عملوند چپ، که برای عملکرد هنگام استفاده از محاسبات پرهزینه یا فراخوانی API مهم است.
val name: String? = getUserName()
val displayName = name ?: "Guest"
fun getLength(str: String?): Int {
return str?.length ?: 0
}
val config: Config? = loadConfig()
val timeout = config?.timeout ?: 30
println("مهلت زمانی: $timeout")
// Elvis با throw برای پارامترهای اجباری
val requiredId = nullableId ?: throw IllegalArgumentException("ID is required")
// Elvis با return برای خروج زودهنگام
fun process(data: String?): Result {
val safe = data ?: return Result.failure("No data")
return processInternal(safe)
}
ترکیب با let — الگوی رایج در Kotlin، که در آن Elvis Operator مقدار پیشفرض را تعیین میکند و let عمل را با نتیجه غیر null انجام میدهد. چنین رویکردی بلوکهای کامل if-else را با یک زنجیره فراخوانی بدون کاهش خوانایی جایگزین میکند. Elvis Operator همچنین میتواند با throw برای قطع اجباری در صورت عدم وجود پارامتر اجباری استفاده شود — این یک روش اصطلاحی برای اعتبارسنجی دادههای ورودی است.
در Kotlin الگوی Elvis + return رایج است. اگر مقدار null باشد، تابع بلافاصله نتیجه را برمیگرداند یا استثنا پرتاب میکند. اصطلاح «Elvis with return» اغلب در توابع تبدیل داده استفاده میشود: val processed = rawData ?: return defaultValue. این فشردهتر از guard let در Swift است و تو رفتگی کد را افزایش نمیدهد.
Elvis Operator کوتاهتر از if-else است و نیازی به تکرار متغیر ندارد. مقایسه کنید: val x = a ?: b در مقابل val x = if (a != null) a else b. در عبارات پیچیده کاهش کد به 60% میرسد، در حالی که معنا کاملاً یکسان است — کامپایلر میتواند بایت کد یکسانی برای هر دو گزینه تولید کند.
| معیار | Elvis Operator | if-else |
|---|---|---|
| طول نوشتار | 1 خط، 5–10 کاراکتر | 3 خط، 15–30 کاراکتر |
| تکرار عبارت | خیر | بله (a != null) ? a : b |
| تنبل بودن بخش راست | بله | بله (elvis کوتاهتر) |
| اثرات جانبی | فقط در بخش راست | در هر دو شاخه |
| خوانایی | بالا برای موارد ساده | بهتر برای منطق پیچیده |
Elvis Operator برای انتساب مقدار پیشفرض، فراخوانی زنجیرهای توابع با دسترسی امن و لاگگیری مقادیر缺失 بهینه است. الگوهای اصطلاحی Kotlin آن را به عنوان جایگزین if-else برای بررسیهای ساده null در عبارات توصیه میکند. در ترکیب با ?. زنجیرههای فشرده بدون متغیرهای موقت ایجاد میکند.
if-else در شرایط چندگانه، زمانی که نیاز به انجام اثرات جانبی است یا زمانی که هر دو عملوند بلوکهای کد پیچیده با چندین عملیات هستند، ترجیح داده میشود. Elvis Operator از بلوکهای تو در تو پشتیبانی نمیکند — فقط عبارات تکی برای هر عملوند. اگر بخش راست تابعی با اثر جانبی را فراخوانی کند، خوانایی if-else بالاتر است.
Groovy دقیقاً از همان نحو ?: مانند Kotlin استفاده میکند، زیرا هر دو زبان روی JVM کار میکنند و فلسفه null-safety را به اشتراک میگذارند. در Groovy این عملگر زودتر ظاهر شد — از نسخه 1.8 که در سال 2011 منتشر شد در زبان وجود داشت. Groovy همچنین از انتساب Elvis پشتیبانی میکند: x ?= value (فقط در صورت null بودن x مقداردهی کند).
def name = getUserName()
def display = name ?: "Guest"
def map = ["key": "value"]
def result = map?.get("missing") ?: "default"
println(result)
// انتساب Elvis در Groovy
def config = null
config ?= "defaultConfig"
assert config == "defaultConfig"
در Swift معادل nil-coalescing operator نامیده میشود و به صورت ?? نوشته میشود. در Dart از همان نحو ?? استفاده میشود. تفاوت در این است که Swift و Dart نیاز به تطابق نوع عملوندها دارند، در حالی که Kotlin انواع مختلف را با تبدیل خودکار به ابرنوع مشترک مجاز میداند. در TypeScript از نسخه 3.7 عملگر ?? (nullish coalescing) ظاهر شد که فقط با null و undefined کار میکند، برخلاف || که تمام مقادیر falsy را فیلتر میکند. در PHP از نسخه 7.0 عملگر ??، در C# — ?? از نسخه 6.0 ظاهر شد.
رایجترین اشتباه — اشتباه گرفتن Elvis Operator ?: با عملگر فراخوانی امن ?. در Kotlin ?. متد یا ویژگی را فقط در صورت null نبودن شیء فراخوانی میکند، در حالی که ?: مقدار پیشفرض را در صورت null برمیگرداند. آنها به صورت متوالی ترکیب میشوند، اما هر کدام عملکرد خود را انجام میدهند. سردرگمی در مبتدیانی رخ میدهد که سعی میکنند از ?: بدون ?. قبل از آن استفاده کنند.
بخش راست Elvis به صورت تنبلانه محاسبه میشود، اما اگر در آن فراخوانی تابعی با اثرات جانبی قرار داشته باشد، این میتواند منجر به رفتار غیرمنتظره شود. توسعهدهندگان گاهی در بخش راست محاسبات پرهزینه یا لاگگیری قرار میدهند که در صورت وجود مقدار غیر null اجرا نمیشود. مهم است به خاطر داشته باشیم که بخش راست عبارتی است که فقط در صورت لزوم محاسبه میشود.
چندین Elvis متوالی میتوانند خواندن کد را دشوار کنند. به عنوان مثال، a ?: b ?: c ?: d از چپ به راست اجرا میشود و اولین غیر null را برمیگرداند. گروهبندی با پرانتز یا استخراج منطق به یک تابع جداگانه خوانایی را افزایش میدهد و دیباگ را آسانتر میکند. اگر زنجیره طولانیتر از 3 عنصر است، بهتر است از عبارت when یا تابع کمکی استفاده شود.
توسعهدهندگان تازهکار گاهی سعی میکنند از Elvis Operator برای بررسی مقادیر boolean استفاده کنند: val x = flag ?: false. این فقط در صورتی کار میکند که flag میتواند null باشد. برای شرایط boolean بدون null به if-else معمولی یا عملگر سهتایی نیاز است که در Kotlin وجود ندارد، اما عبارت if-else جایگزین آن میشود: val x = if (flag) a else b.
سوالات متداول
Elvis Operator فقط null را بررسی میکند، در حالی که عملگر سهتایی هر شرط boolean را میپذیرد. در Kotlin عملگر سهتایی وجود ندارد — عبارت if-else جایگزین آن میشود. Elvis یک وظیفه خاص را حل میکند: مقدار پیشفرض در صورت null، در حالی که عملگر سهتایی تمام عبارات شرطی را پوشش میدهد.
بله، در بخش راست میتواند فراخوانی تابع باشد: val x = a ?: calculateDefault(). تابع فقط در صورت null بودن مقدار a به لطف محاسبه تنبلانه فراخوانی میشود. این امکان استفاده از محاسبات پرهزینه، فراخوانی API یا پرسوجوهای پایگاه داده را بدون کاهش عملکرد در صورت وجود مقدار فراهم میکند.
در Java Elvis Operator مستقیم وجود ندارد. از Java 8 میتوان از Optional.ofNullable(value).orElse(default) استفاده کرد. در Java 14+ عبارات switch ظاهر شدند، اما ?: کامل وجود ندارد. Kotlin و Groovy آن را به عنوان یک ساختار نحوی داخلی زبان ارائه میدهند.
الگوی معمول: safe call ?. سپس Elvis. مثال: user?.address?.city ?: "Unknown". اگر هر عنصری از زنجیره null باشد — مقدار پیشفرض برگردانده میشود. این جایگزین فشردهای برای بررسیهای if تو در تو است که کد را 3–5 برابر در مقایسه با رویکرد سنتی کاهش میدهد.
Elvis Operator یک ساختار نحوی در سطح زبان است، orElse یک متد Optional در Java است. Elvis به صورت تنبلانه اجرا میشود (بخش راست فقط در صورت null محاسبه میشود)، orElse همیشه آرگومان را محاسبه میکند. برای گزینه تنبلانه در Java orElseGet وجود دارد که Supplier میپذیرد. Elvis کوتاهتر است و نیازی به ایجاد Optional ندارد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید