Elvis Operator: چیست، نحو و处理 مقادیر null

نویسنده: IT Sectr منتشر شده: 2026-05-27 زمان مطالعه: 8 دقیقه

Elvis Operator — یک عملگر دودویی است که اگر عملوند چپ null نباشد آن را برمی‌گرداند، در غیر این صورت عملوند راست را برمی‌گرداند. در Kotlin، Groovy و برخی زبان‌های دیگر به صورت ?: نوشته می‌شود. بر اساس Kotlin Language Documentation, 2024، این عملگر بخشی از سیستم null-safety زبان است و به شما امکان می‌دهد ساختارهای شرطی را بدون کاهش خوانایی به یک خط کاهش دهید. برخلاف نوشتار کامل if-else، Elvis Operator بخش راست را فقط در صورت null بودن مقدار چپ محاسبه می‌کند که در استفاده از عبارات پرهزینه پیش‌فرض مزیت عملکردی ایجاد می‌کند.

نکات اصلی

  • Elvis Operator — عملگر ?: که اولین عملوند غیر null را از دو عملوند برمی‌گرداند
  • Null safety — حوزه کلیدی کاربرد Elvis Operator در Kotlin و سایر زبان‌ها
  • نحو بسیار مختصر است: val result = a ?: b، معادل if (a != null) a else b
  • Groovy از همان نحو ?: استفاده می‌کند، Swift — عملگر ??، Dart — ??
  • لاگ‌گیری از طریق Elvis Operator — الگوی محبوب: val name = input ?: "default"

Elvis Operator چیست

Elvis Operator — یک عملگر دودویی است که به افتخار مدل موی الویس پریسلی نامگذاری شده است. نماد ?: از نظر بصری چهره خواننده را از نمای نیمرخ تداعی می‌کند: علامت سوال — چشم و ساقه مو، دو نقطه — دهان. عملگر دو عملوند می‌پذیرد: اگر اولی null نباشد — آن برگردانده می‌شود، در غیر این صورت دومی برگردانده می‌شود. این امکان جایگزینی ساختار کامل if-else با یک نوشتار کوتاه را فراهم می‌کند.

ریشه نام

نام «Elvis Operator» در جامعه Kotlin و Groovy تثبیت شد و سپس به Xtend و سایر زبان‌های JVM منتقل شد. در Swift و Dart ساختار مشابه nil-coalescing operator نامیده می‌شود، اما از نظر عملکردی یکسان است. تداعی بصری با الویس پریسلی به این عملگر کمک کرد تا به یکی از شناخته‌شده‌ترین نمادها در نحو زبان‌های برنامه‌نویسی مدرن تبدیل شود.

نقش در پردازش null

Elvis Operator بخشی از سیستم null safety است که از NullPointerException (NPE) جلوگیری می‌کند. بر اساس تحقیقات JetBrains در سال 2023، NPE 28% از تمام استثناها را در کد تولیدی روی JVM تشکیل می‌دهد. استفاده از Elvis Operator در نقطه انتساب کاملاً NPE را حذف می‌کند و مقدار پیش‌فرض را تضمین می‌کند. در ترکیب با عملگر فراخوانی امن ?. یک زنجیره قابل اعتماد بدون هیچ بلوک if به دست می‌آید.

نحو Elvis Operator در Kotlin

در Kotlin Elvis Operator به صورت ?: بین دو عبارت نوشته می‌شود. اگر عبارت چپ null نباشد — نتیجه برابر با چپ است، در غیر این صورت عبارت راست محاسبه می‌شود. عبارت راست تنبلانه محاسبه می‌شود — فقط در صورت null بودن عملوند چپ، که برای عملکرد هنگام استفاده از محاسبات پرهزینه یا فراخوانی API مهم است.

kotlin
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 برای قطع اجباری در صورت عدم وجود پارامتر اجباری استفاده شود — این یک روش اصطلاحی برای اعتبارسنجی داده‌های ورودی است.

Elvis با خروج زودهنگام از تابع

در Kotlin الگوی Elvis + return رایج است. اگر مقدار null باشد، تابع بلافاصله نتیجه را برمی‌گرداند یا استثنا پرتاب می‌کند. اصطلاح «Elvis with return» اغلب در توابع تبدیل داده استفاده می‌شود: val processed = rawData ?: return defaultValue. این فشرده‌تر از guard let در Swift است و تو رفتگی کد را افزایش نمی‌دهد.

مقایسه Elvis Operator و if-else

Elvis Operator کوتاه‌تر از if-else است و نیازی به تکرار متغیر ندارد. مقایسه کنید: val x = a ?: b در مقابل val x = if (a != null) a else b. در عبارات پیچیده کاهش کد به 60% می‌رسد، در حالی که معنا کاملاً یکسان است — کامپایلر می‌تواند بایت کد یکسانی برای هر دو گزینه تولید کند.

معیارElvis Operatorif-else
طول نوشتار1 خط، 5–10 کاراکتر3 خط، 15–30 کاراکتر
تکرار عبارتخیربله (a != null) ? a : b
تنبل بودن بخش راستبلهبله (elvis کوتاه‌تر)
اثرات جانبیفقط در بخش راستدر هر دو شاخه
خواناییبالا برای موارد سادهبهتر برای منطق پیچیده

چه زمانی از Elvis Operator استفاده کنیم

Elvis Operator برای انتساب مقدار پیش‌فرض، فراخوانی زنجیره‌ای توابع با دسترسی امن و لاگ‌گیری مقادیر缺失 بهینه است. الگوهای اصطلاحی Kotlin آن را به عنوان جایگزین if-else برای بررسی‌های ساده null در عبارات توصیه می‌کند. در ترکیب با ?. زنجیره‌های فشرده بدون متغیرهای موقت ایجاد می‌کند.

چه زمانی if-else ترجیح داده می‌شود

if-else در شرایط چندگانه، زمانی که نیاز به انجام اثرات جانبی است یا زمانی که هر دو عملوند بلوک‌های کد پیچیده با چندین عملیات هستند، ترجیح داده می‌شود. Elvis Operator از بلوک‌های تو در تو پشتیبانی نمی‌کند — فقط عبارات تکی برای هر عملوند. اگر بخش راست تابعی با اثر جانبی را فراخوانی کند، خوانایی if-else بالاتر است.

Elvis Operator در سایر زبان‌های برنامه‌نویسی

Groovy دقیقاً از همان نحو ?: مانند Kotlin استفاده می‌کند، زیرا هر دو زبان روی JVM کار می‌کنند و فلسفه null-safety را به اشتراک می‌گذارند. در Groovy این عملگر زودتر ظاهر شد — از نسخه 1.8 که در سال 2011 منتشر شد در زبان وجود داشت. Groovy همچنین از انتساب Elvis پشتیبانی می‌کند: x ?= value (فقط در صورت null بودن x مقداردهی کند).

groovy
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

رایج‌ترین اشتباه — اشتباه گرفتن Elvis Operator ?: با عملگر فراخوانی امن ?. در Kotlin ?. متد یا ویژگی را فقط در صورت null نبودن شیء فراخوانی می‌کند، در حالی که ?: مقدار پیش‌فرض را در صورت null برمی‌گرداند. آنها به صورت متوالی ترکیب می‌شوند، اما هر کدام عملکرد خود را انجام می‌دهند. سردرگمی در مبتدیانی رخ می‌دهد که سعی می‌کنند از ?: بدون ?. قبل از آن استفاده کنند.

اثرات جانبی در عملوند راست

بخش راست Elvis به صورت تنبلانه محاسبه می‌شود، اما اگر در آن فراخوانی تابعی با اثرات جانبی قرار داشته باشد، این می‌تواند منجر به رفتار غیرمنتظره شود. توسعه‌دهندگان گاهی در بخش راست محاسبات پرهزینه یا لاگ‌گیری قرار می‌دهند که در صورت وجود مقدار غیر null اجرا نمی‌شود. مهم است به خاطر داشته باشیم که بخش راست عبارتی است که فقط در صورت لزوم محاسبه می‌شود.

زنجیره‌های Elvis بدون گروه‌بندی

چندین Elvis متوالی می‌توانند خواندن کد را دشوار کنند. به عنوان مثال، a ?: b ?: c ?: d از چپ به راست اجرا می‌شود و اولین غیر null را برمی‌گرداند. گروه‌بندی با پرانتز یا استخراج منطق به یک تابع جداگانه خوانایی را افزایش می‌دهد و دیباگ را آسان‌تر می‌کند. اگر زنجیره طولانی‌تر از 3 عنصر است، بهتر است از عبارت when یا تابع کمکی استفاده شود.

Elvis به جای if-else با شرایط boolean

توسعه‌دهندگان تازه‌کار گاهی سعی می‌کنند از 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 چه تفاوتی با عملگر سه‌تایی دارد؟

Elvis Operator فقط null را بررسی می‌کند، در حالی که عملگر سه‌تایی هر شرط boolean را می‌پذیرد. در Kotlin عملگر سه‌تایی وجود ندارد — عبارت if-else جایگزین آن می‌شود. Elvis یک وظیفه خاص را حل می‌کند: مقدار پیش‌فرض در صورت null، در حالی که عملگر سه‌تایی تمام عبارات شرطی را پوشش می‌دهد.

آیا می‌توان از Elvis Operator با توابع استفاده کرد؟

بله، در بخش راست می‌تواند فراخوانی تابع باشد: val x = a ?: calculateDefault(). تابع فقط در صورت null بودن مقدار a به لطف محاسبه تنبلانه فراخوانی می‌شود. این امکان استفاده از محاسبات پرهزینه، فراخوانی API یا پرس‌وجوهای پایگاه داده را بدون کاهش عملکرد در صورت وجود مقدار فراهم می‌کند.

آیا Elvis Operator در Java وجود دارد؟

در Java Elvis Operator مستقیم وجود ندارد. از Java 8 می‌توان از Optional.ofNullable(value).orElse(default) استفاده کرد. در Java 14+ عبارات switch ظاهر شدند، اما ?: کامل وجود ندارد. Kotlin و Groovy آن را به عنوان یک ساختار نحوی داخلی زبان ارائه می‌دهند.

Elvis Operator چگونه با زنجیره‌های فراخوانی کار می‌کند؟

الگوی معمول: safe call ?. سپس Elvis. مثال: user?.address?.city ?: "Unknown". اگر هر عنصری از زنجیره null باشد — مقدار پیش‌فرض برگردانده می‌شود. این جایگزین فشرده‌ای برای بررسی‌های if تو در تو است که کد را 3–5 برابر در مقایسه با رویکرد سنتی کاهش می‌دهد.

تفاوت بین Elvis Operator و orElse در Optional چیست؟

Elvis Operator یک ساختار نحوی در سطح زبان است، orElse یک متد Optional در Java است. Elvis به صورت تنبلانه اجرا می‌شود (بخش راست فقط در صورت null محاسبه می‌شود)، orElse همیشه آرگومان را محاسبه می‌کند. برای گزینه تنبلانه در Java orElseGet وجود دارد که Supplier می‌پذیرد. Elvis کوتاه‌تر است و نیازی به ایجاد Optional ندارد.

خلاصه

  • Elvis Operator — عملگر ?: برای تعیین مقدار پیش‌فرض در صورت null بودن عملوند
  • نحو در Kotlin و Groovy: val result = a ?: b، که در آن b فقط در صورت a == null محاسبه می‌شود
  • Null safety — حوزه اصلی کاربرد، جلوگیری از NullPointerException
  • Nil-coalescing — معادل در Swift (??) و Dart (??) با معنای مشابه، در TypeScript — ?? از نسخه 3.7
  • ترکیب با safe call ?. زنجیره فشرده پردازش مقادیر null بدون تو رفتگی ایجاد می‌کند
  • محاسبه تنبلانه عملوند راست — تفاوت کلیدی با عملگر سه‌تایی
  • Best practice — استفاده برای بررسی‌های ساده null، اجتناب در بلوک‌های پیچیده با اثرات جانبی

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید