021-88881776

آموزش سینتکس های پایه

آموزش سینتکس های پایه نقطه ورود (Entry Point) برنامه در Kotlin جایی است که اجرای برنامه از آنجا آغاز می‌شود و معمولاً تابع اصلی یا `main` است. تابع `main` در Kotlin مشابه زبان‌های دیگر مانند جاوا است، اما Kotlin انعطاف‌پذیری بیشتری در تعریف این تابع ارائه می‌دهد. در این مقاله، به معرفی و جزئیات تابع `main` در Kotlin، ساختار آن، پارامترها، و نکات مهم مرتبط با نقطه ورود برنامه خواهیم پرداخت.

تابع `main` در Kotlin

در Kotlin، تابع `main` همانند سایر زبان‌ها نقطه ورود برنامه است و کدی که در این تابع نوشته می‌شود در ابتدای اجرای برنامه فراخوانی می‌شود. ساختار تابع `main` در Kotlin به صورت زیر است:

fun main() {
    println("Hello, Kotlin!")
}

این تابع بدون پارامتر تعریف شده است و در اجرای ساده برنامه‌ها یا پروژه‌های آموزشی معمولاً به همین شکل نوشته می‌شود.

آرگومان‌های خط فرمان

Kotlin همچنین اجازه می‌دهد که تابع `main` پارامترهای خط فرمان (Command-Line Arguments) را بگیرد. برای این منظور، می‌توان تابع `main` را به شکل زیر تعریف کرد:

fun main(args: Array<String>) {
    println("Arguments: ${args.joinToString()}")
}

در این نسخه از تابع `main`، پارامتر `args` یک آرایه از نوع `String` است که مقادیر خط فرمان هنگام اجرای برنامه در آن قرار می‌گیرند. این ساختار برای برنامه‌هایی که نیاز به ورودی‌های خارجی دارند مناسب است.

نکات مهم در مورد تابع `main`

1. سادگی و خوانایی: یکی از مزایای Kotlin، حذف نیاز به نوشتن کلاس اصلی برای تعریف تابع `main` است که منجر به کدی خواناتر و کوتاه‌تر می‌شود.
2. پشتیبانی از چندین نقطه ورود: در Kotlin می‌توانید چندین تابع `main` در فایل‌های مختلف داشته باشید، اما برای اجرای برنامه باید یکی از این توابع به عنوان نقطه ورود انتخاب شود.
3. سازگاری با JVM: تابع `main` در Kotlin به‌گونه‌ای طراحی شده است که سازگاری کاملی با JVM دارد و می‌تواند به صورت یک برنامه مستقل اجرا شود.

تعریف تابع `main` با `vararg`

برای تعریف تابع `main` که تعداد نامشخصی از آرگومان‌های `String` را بپذیرد، می‌توان از کلمه کلیدی `vararg` استفاده کرد. این کلمه کلیدی مشخص می‌کند که تابع می‌تواند تعداد دلخواهی از پارامترها را بپذیرد و آن‌ها را به صورت یک آرایه پردازش کند. مثال زیر نحوه تعریف این شکل از تابع `main` را نشان می‌دهد:

fun main(vararg args: String) {
    println("Arguments: ${args.joinToString()}")
}

در اینجا، `args` یک آرایه از نوع `String` است که می‌تواند تعداد دلخواهی از آرگومان‌ها را شامل شود. این روش بسیار منعطف است و استفاده از آن به‌ویژه در شرایطی که تعداد آرگومان‌های ورودی متغیر است، مفید واقع می‌شود.

 نحوه اجرای تابع `main` با `vararg`

برای اجرای این تابع، می‌توانید آرگومان‌های خط فرمان را هنگام اجرای برنامه ارسال کنید. به عنوان مثال، اگر برنامه شما به صورت زیر اجرا شود:

kotlin MainKt Hello Kotlin World

در اینجا `args` شامل مقادیر `Hello`، `Kotlin` و `World` خواهد بود و خروجی برنامه به صورت زیر خواهد بود:

Arguments: Hello, Kotlin, World

 نکات کاربردی و تفاوت‌ها

1. انعطاف‌پذیری در تعداد پارامترها: استفاده از `vararg` به شما این امکان را می‌دهد که تابع `main` را بدون نیاز به مشخص کردن دقیق تعداد پارامترها، برای پردازش ورودی‌های مختلف به کار ببرید.
2. تبدیل به آرایه: در صورت نیاز، می‌توانید با استفاده از متدهایی مانند `toList()`، آرایه `args` را به یک لیست تبدیل کنید تا دسترسی بهتری به پارامترها داشته باشید.
3. ترکیب با دیگر پارامترها: در Kotlin، پارامترهای `vararg` می‌توانند در کنار دیگر پارامترها استفاده شوند، به شرطی که `vararg` آخرین پارامتر نباشد.

 مثال کاربردی

مثال زیر یک برنامه کوچک را نشان می‌دهد که با استفاده از تابع `main` و `vararg` یک سری اعداد را دریافت می‌کند و جمع آن‌ها را محاسبه و نمایش می‌دهد.

fun main(vararg numbers: String) {
    val sum = numbers.map { it.toIntOrNull() ?: 0 }.sum()
    println("Sum of numbers: $sum")
}

در این برنامه:
– تابع `main` تعداد نامشخصی از آرگومان‌ها را می‌پذیرد.
– با استفاده از متد `map`، هر آرگومان را به عدد صحیح تبدیل می‌کند. اگر یک آرگومان قابل تبدیل نباشد، مقدار صفر (`0`) را برای آن در نظر می‌گیرد.
– سپس با استفاده از `sum`، جمع تمام اعداد محاسبه و چاپ می‌شود.

اگر برنامه به شکل زیر اجرا شود:

kotlin MainKt 10 20 30

خروجی برنامه به صورت زیر خواهد بود:

Sum of numbers: 60

 

تابع `print`

در زبان برنامه‌نویسی Kotlin، تابع `print` و نسخه پیشرفته‌تر آن `println` برای چاپ داده‌ها به خروجی استاندارد (معمولاً صفحه کنسول) به کار می‌روند. این توابع بسیار ساده و پرکاربرد هستند و در تمام برنامه‌ها برای نمایش اطلاعات، رفع خطا و حتی دیباگ کردن مورد استفاده قرار می‌گیرند. در این مقاله، به معرفی این توابع، تفاوت‌های آن‌ها، مثال‌ها و نکات مهم استفاده از آن‌ها در Kotlin می‌پردازیم.

تابع `print` در Kotlin یک آرگومان ورودی می‌گیرد و آن را بدون اضافه کردن خط جدید به انتهای خروجی، در خروجی استاندارد چاپ می‌کند. این تابع از هر نوع داده‌ای که به `String` قابل تبدیل باشد، پشتیبانی می‌کند و آن داده را مستقیماً به خروجی می‌فرستد.

ساختار `print`

fun main() {
    print("Hello, Kotlin!")
    print(" How are you?")
}

خروجی این کد به صورت زیر خواهد بود:

Hello, Kotlin! How are you?

همان‌طور که می‌بینید، هیچ خط جدیدی بین `Hello, Kotlin!` و `How are you?` اضافه نشده است، زیرا `print` به‌طور پیش‌فرض از خط جدید استفاده نمی‌کند.

 تابع `println`

تابع `println` مشابه `print` عمل می‌کند، با این تفاوت که بعد از چاپ داده‌ها، یک خط جدید به انتهای آن اضافه می‌کند. این ویژگی باعث می‌شود که هر بار استفاده از `println` خروجی در خط بعدی چاپ شود.

ساختار `println`

fun main() {
    println("Hello, Kotlin!")
    println("How are you?")
}

خروجی این کد به صورت زیر خواهد بود:

Hello, Kotlin!
How are you?

در اینجا، `println` پس از چاپ هر خط، به صورت خودکار به خط جدید منتقل می‌شود، که خوانایی خروجی را افزایش می‌دهد.

 تفاوت‌های `print` و `println`

1خط جدید: تفاوت اصلی `print` و `println` این است که `println` بعد از چاپ داده، به خط جدید منتقل می‌شود، در حالی که `print` این کار را انجام نمی‌دهد.
2. خوانایی: استفاده از `println` در زمانی که می‌خواهید خروجی‌های مجزا در خطوط جداگانه نمایش داده شوند، ترجیح داده می‌شود.
3.کاهش نیاز به نوشتن کاراکترهای خاص: اگر بخواهید از `print` استفاده کنید و به خط جدید بروید، باید از کاراکتر `\n` استفاده کنید، در حالی که `println` این کار را به صورت خودکار انجام می‌دهد.

استفاده از `print` و `println` با انواع داده‌ها

در Kotlin، می‌توان از `print` و `println` برای چاپ انواع داده‌ها (مانند `Int`، `Double`، `Boolean` و …) استفاده کرد. Kotlin به‌طور خودکار داده‌ها را به `String` تبدیل می‌کند و در خروجی نمایش می‌دهد.

مثال زیر نشان می‌دهد که چگونه انواع داده مختلف را چاپ کنید:

fun main() {
    val number = 10
    val pi = 3.14
    val isKotlinFun = true

    println("Number: $number")
    println("Pi value: $pi")
    println("Is Kotlin fun? $isKotlinFun")
}

خروجی:

Number: 10
Pi value: 3.14
Is Kotlin fun? true

 استفاده از `print` و `println` با رشته‌های قالب‌بندی شده

Kotlin از یک ویژگی به نام **رشته‌های قالب‌بندی شده (String Templates)** پشتیبانی می‌کند که امکان چاپ مقادیر متغیرها را در داخل رشته‌ها به راحتی فراهم می‌کند. این قابلیت از `$` برای درج متغیرها و `${}` برای استفاده از عبارات پیچیده‌تر استفاده می‌کند.

مثال:

fun main() {
    val name = "Kotlin"
    val age = 10

    println("Hello, $name!")
    println("$name is $age years old.")
    println("In 5 years, $name will be ${age + 5} years old.")
}

خروجی:

 

Hello, Kotlin!
Kotlin is 10 years old.
In 5 years, Kotlin will be 15 years old.

چاپ خروجی‌های پیچیده‌تر

در برنامه‌های واقعی، ممکن است نیاز داشته باشید که خروجی‌های پیچیده‌تری مانند لیست‌ها، آرایه‌ها، و اشیاء را چاپ کنید. Kotlin به شما این امکان را می‌دهد که با استفاده از `print` و `println`، انواع داده‌ها و مجموعه‌های پیچیده را چاپ کنید.

مثال چاپ لیست:

fun main() {
    val list = listOf("Apple", "Banana", "Cherry")
    println("Fruits: $list")
}

خروجی:

Fruits: [Apple, Banana, Cherry]

تابع `readln()

تابع `readln` در Kotlin برای خواندن ورودی کاربر از ورودی استاندارد (کیبورد) استفاده می‌شود و ورودی کاربر را به صورت یک رشته (`String`) برمی‌گرداند. این تابع، کل خطی را که کاربر وارد می‌کند (تا زمانی که کلید Enter فشرده شود) به عنوان یک رشته می‌خواند. از این تابع می‌توان برای دریافت اطلاعات متنی مانند نام، سن، یا هر داده دیگری که کاربر وارد می‌کند، استفاده کرد.

fun main() {
    println("Please enter your name:")
    val name = readln()
    println("Hello, $name!")
}

در این مثال:
1. ابتدا با استفاده از `println` از کاربر درخواست می‌کنیم که نام خود را وارد کند.
2. سپس با `readln`، ورودی کاربر را می‌خوانیم و آن را در متغیر `name` ذخیره می‌کنیم.
3. در نهایت، با استفاده از `println` پیام خوش‌آمدگویی همراه با نام کاربر چاپ می‌شود.

تفاوت `print` و `println`

`print`: متن را در خروجی استاندارد چاپ می‌کند اما به خط جدید نمی‌رود. در نتیجه، هر چیز دیگری که بعد از آن چاپ شود، در همان خط قرار می‌گیرد.

`println`: متن را چاپ کرده و سپس به خط جدید منتقل می‌شود. این روش، به ویژه برای نمایش پیام‌هایی که نیاز به سازمان‌دهی در چندین خط دارند، مناسب است.

 درخواست ورودی از کاربر با استفاده از `print` و `readln`

برای درخواست ورودی از کاربر، می‌توانید از `print` یا `println` استفاده کنید تا پیام درخواستی شما چاپ شود. سپس با استفاده از `readln` می‌توانید پاسخ کاربر را بگیرید.

fun main() {
    print("Enter your age: ")
    val age = readln()
    println("Your age is $age.")
}

در اینجا:
1. از `print` استفاده شده است تا پیام درخواستی (`Enter your age:`) بدون انتقال به خط بعدی چاپ شود.
2. تابع `readln` منتظر می‌ماند تا کاربر عددی را وارد کند و آن را به عنوان یک رشته در متغیر `age` ذخیره می‌کند.
3. سپس `println` مقدار وارد شده توسط کاربر را در یک جمله نشان می‌دهد.

تبدیل ورودی به نوع داده‌های دیگر

ورودی خوانده شده از `readln` به صورت رشته است. برای استفاده از داده‌های عددی، باید این مقدار را به نوع عددی مناسب تبدیل کنید.

مثال تبدیل رشته ورودی به عدد صحیح (`Int`):

fun main() {
    print("Enter your birth year: ")
    val birthYear = readln().toInt()
    val age = 2024 - birthYear
    println("You are approximately $age years old.")
}

در اینجا:
1. تابع `readln().toInt()` سال تولد را به عدد صحیح تبدیل می‌کند.
2. سپس با انجام یک محاسبه، سن تقریبی کاربر را نشان می‌دهیم.

Functions در آموزش سینتکس های پایه

این توابع، Kotlin را به زبانی ساده و قدرتمند برای ایجاد برنامه‌های تعاملی تبدیل می‌کنند.

در زبان Kotlin، می‌توانید یک تابع با دو پارامتر از نوع `Int` و نوع بازگشتی `Int` ایجاد کنید. این تابع می‌تواند عملیات مختلفی را روی پارامترهای ورودی انجام داده و نتیجه را به صورت عدد صحیح (`Int`) برگرداند. در ادامه، مثالی از چنین تابعی و نحوه تعریف و استفاده از آن را آورده‌ام.

 تعریف تابع با دو پارامتر `Int` و نوع بازگشتی `Int`

برای تعریف یک تابع که دو پارامتر `Int` می‌گیرد و یک مقدار `Int` برمی‌گرداند، می‌توانید از ساختار زیر استفاده کنید:

fun addNumbers(a: Int, b: Int): Int {
    return a + b
}

در این مثال:
– `addNumbers` نام تابع است.
– `a` و `b` پارامترهای ورودی از نوع `Int` هستند.
– `Int` بعد از علامت `:` نشان‌دهنده نوع بازگشتی تابع است.
– `return a + b` نتیجه جمع دو پارامتر ورودی را برمی‌گرداند.

 فراخوانی تابع

می‌توانید این تابع را در تابع `main` فراخوانی کرده و نتیجه آن را چاپ کنید:

fun main() {
    val result = addNumbers(5, 3)
    println("The result is: $result")
}

خروجی این کد به صورت زیر خواهد بود:

The result is: 8

مثال‌های دیگر
می‌توانید این ساختار را برای توابع مختلفی که عملیات متفاوتی روی دو عدد صحیح انجام می‌دهند، به کار ببرید. برای مثال:

 تابع ضرب

fun multiplyNumbers(a: Int, b: Int): Int {
    return a * b
}

تابع تفریق

fun subtractNumbers(a: Int, b: Int): Int {
    return a - b
}

 تعریف توابع کوتاه با `=`

در Kotlin، می‌توانید توابع ساده را به شکل کوتاه‌تری نیز بنویسید:

fun addNumbers(a: Int, b: Int): Int = a + b

در این روش، نیازی به استفاده از `return` نیست و Kotlin به‌طور خودکار نتیجه عبارت را به عنوان خروجی تابع برمی‌گرداند.

معرفی متغیرها

در Kotlin، هر متغیر با یک نوع داده خاص تعریف می‌شود. این نوع داده می‌تواند عددی، متنی، بولی و یا هر نوع دیگری باشد. به صورت پیش‌فرض، می‌توان از ویژگی استنتاج نوع (Type Inference) Kotlin استفاده کرد و نوع داده متغیر را مشخص نکرد؛ Kotlin به طور خودکار نوع داده را تشخیص می‌دهد.

val name = "John Doe" // Kotlin به صورت خودکار نوع String را تشخیص می‌دهد

استفاده از `val`

کلمه کلیدی `val` برای تعریف متغیرهایی استفاده می‌شود که تنها یک بار مقداردهی می‌شوند و پس از آن نمی‌توان مقدار دیگری به آن‌ها اختصاص داد. این متغیرها به نوعی شبیه به مفهوم “ثابت” (constant) در دیگر زبان‌های برنامه‌نویسی هستند. به عبارت دیگر، `val` به معنی متغیرهای فقط خواندنی (Read-Only) است که پس از مقداردهی اولیه، مقدارشان تغییر نمی‌کند.

val pi = 3.14159
val name = "Sara"

در این مثال‌ها، متغیر `pi` و `name` با استفاده از `val` تعریف شده‌اند و دیگر امکان تغییر مقدار آن‌ها در طول برنامه وجود ندارد.

 کاربردهای `val`
استفاده از `val` زمانی مفید است که داده‌ای ثابت داشته باشیم و قصد نداریم در طول اجرای برنامه آن را تغییر دهیم. این موضوع باعث می‌شود که برنامه نویسی با امنیت بالاتری انجام شود، زیرا به صورت ضمنی نشان می‌دهد که این متغیر فقط یک بار مقداردهی می‌شود و دیگر دستکاری نمی‌شود.

استفاده از `var`

کلمه کلیدی `var` برای تعریف متغیرهای قابل تغییر استفاده می‌شود. این متغیرها پس از مقداردهی اولیه قابل تغییر و به‌روزرسانی هستند.

var age = 25
age = 30

در این مثال، مقدار متغیر `age` ابتدا 25 تعیین شده است، اما بعداً می‌توان آن را به 30 تغییر داد. `var` برای متغیرهایی کاربرد دارد که مقدارشان در طول اجرای برنامه تغییر می‌کند.

کاربردهای `var`
در مواقعی که نیاز به تغییر مقادیر داریم و باید داده‌ها را در طول برنامه به‌روزرسانی کنیم، `var` بسیار مفید است. به طور مثال در شمارنده‌ها، زمان‌بندی‌ها و متغیرهایی که به صورت پویا تغییر می‌کنند، از `var` استفاده می‌شود.

 نوع داده‌ها در متغیرها

همان‌طور که اشاره شد، Kotlin از استنتاج نوع داده استفاده می‌کند؛ یعنی اگر نوع داده را به‌طور واضح مشخص نکنیم، Kotlin با توجه به مقدار اولیه متغیر، نوع داده را تعیین می‌کند. با این حال، می‌توان نوع داده را به صورت صریح نیز مشخص کرد.

val count: Int = 10
var price: Double = 19.99

قوانین استفاده از `val` و `var`

* از `val` برای متغیرهایی استفاده کنید که قرار نیست مقدارشان تغییر کند.
* از `var` برای متغیرهایی استفاده کنید که مقدارشان در طول اجرای برنامه تغییر می‌کند.

 مزایای استفاده از `val` در Kotlin

1. بهبود امنیت کد: چون `val` فقط یک بار مقداردهی می‌شود، احتمال بروز خطاهای ناشی از تغییرات غیرمنتظره کاهش می‌یابد.
2. سازگاری با اصول برنامه‌نویسی تابعی: در برنامه‌نویسی تابعی، استفاده از متغیرهای تغییرناپذیر بسیار توصیه می‌شود و `val` به این اصول پایبند است.
3. کاهش مصرف حافظه: چون متغیرهایی که با `val` تعریف شده‌اند تغییر نمی‌کنند، مدیریت حافظه بهینه‌تر انجام می‌شود.

نکات مهم در رابطه با `val`
– مقداردهی اولیه اجباری است: یک متغیر `val` باید حتماً مقدار اولیه داشته باشد.
– مقداردهی غیرمستقیم: گاهی ممکن است مقداردهی اولیه به صورت غیرمستقیم و در زمان اجرا انجام شود، اما باز هم پس از اولین مقداردهی، دیگر نمی‌توان مقدار آن را تغییر داد.

مثال‌های عملی

استفاده از `val` و `var` در یک برنامه ساده

fun main() {
    val pi = 3.14159 // یک ثابت که مقدار آن تغییر نمی‌کند
    var radius = 5 // متغیری که مقدار آن قابل تغییر است

    println("Circle circumference is: ${2 * pi * radius}")

    radius = 10 // تغییر مقدار radius
    println("Updated circumference is: ${2 * pi * radius}")
}

 تعریف کلاس

برای تعریف یک کلاس ساده در Kotlin، از کلمه کلیدی `class` به همراه نام کلاس استفاده می‌کنیم. یک کلاس می‌تواند شامل ویژگی‌ها (ویژگی‌ها یا متغیرها) و متدها (توابع) باشد که رفتار کلاس را تعیین می‌کنند.

مثال ساده تعریف کلاس

class Person {
    var name: String = ""
    var age: Int = 0

    fun introduce() {
        println("Hello, my name is $name and I am $age years old.")
    }
}

در این مثال، یک کلاس ساده به نام `Person` تعریف شده که دارای دو ویژگی `name` و `age` است. همچنین یک متد به نام `introduce` دارد که اطلاعات شخص را نمایش می‌دهد.

 ایجاد نمونه از کلاس (Instance)

برای ایجاد یک نمونه از کلاس، کافی است از کلمه کلیدی `val` یا `var` به همراه نام کلاس و عملگر `()` استفاده کنیم.

نمونه‌سازی از کلاس `Person`

fun main() {
    val person1 = Person()
    person1.name = "Ali"
    person1.age = 25
    person1.introduce()
}

در این مثال، نمونه‌ای به نام `person1` از کلاس `Person` ایجاد کرده‌ایم و مقادیر `name` و `age` را برای آن تنظیم کرده‌ایم. سپس از متد `introduce` برای نمایش اطلاعات استفاده می‌کنیم.

 سازنده‌ها (Constructors)

Kotlin دو نوع سازنده برای کلاس‌ها فراهم می‌کند: **سازنده اولیه** (Primary Constructor) و **سازنده ثانویه** (Secondary Constructor).

 سازنده اولیه
سازنده اولیه بخشی از تعریف کلاس است و می‌توان آن را در کنار نام کلاس و درون پرانتزها تعریف کرد.

class Person(val name: String, var age: Int) {
    fun introduce() {
        println("Hello, my name is $name and I am $age years old.")
    }
}

در این مثال، `name` و `age` به عنوان پارامترهای سازنده اولیه تعریف شده‌اند و نیازی به تعریف جداگانه آن‌ها نیست.

نمونه‌سازی با سازنده اولیه

fun main() {
    val person1 = Person("Ali", 25)
    person1.introduce()
}

سازنده ثانویه

گاهی اوقات لازم است که علاوه بر سازنده اولیه، سازنده‌های دیگری نیز داشته باشیم. در این موارد، می‌توان از سازنده ثانویه استفاده کرد.

class Person {
    var name: String
    var age: Int

    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }

    fun introduce() {
        println("Hello, my name is $name and I am $age years old.")
    }
}

نمونه‌سازی با سازنده ثانویه

fun main() {
    val person1 = Person("Ali", 25)
    person1.introduce()
}

وراثت (Inheritance)

در Kotlin، کلاس‌ها به طور پیش‌فرض `final` هستند؛ یعنی نمی‌توان از آن‌ها ارث‌بری کرد مگر این‌که با کلمه کلیدی `open` علامت‌گذاری شوند. برای تعریف یک کلاس که قابل ارث‌بری باشد، از `open` استفاده می‌کنیم.

open class Animal(val name: String) {
    open fun sound() {
        println("$name makes a sound.")
    }
}

class Dog(name: String) : Animal(name) {
    override fun sound() {
        println("$name barks.")
    }
}

نمونه‌سازی و استفاده از وراثت

fun main() {
    val dog = Dog("Buddy")
    dog.sound() // خروجی: Buddy barks.
}

کلاس‌های داده‌ای (Data Classes)

در Kotlin، کلاس‌های داده‌ای برای ذخیره داده‌ها طراحی شده‌اند. با استفاده از کلمه کلیدی `data`، می‌توانیم یک کلاس داده‌ای تعریف کنیم. این کلاس‌ها به طور خودکار قابلیت‌هایی مثل `toString()`، `equals()` و `copy()` را فراهم می‌کنند.

data class User(val username: String, val email: String)

 استفاده از کلاس‌های داده‌ای

fun main() {
    val user1 = User("john_doe", "john@example.com")
    println(user1) // خروجی: User(username=john_doe, email=john@example.com)

    val user2 = user1.copy(username = "jane_doe")
    println(user2) // خروجی: User(username=jane_doe, email=john@example.com)
}

 کلاس‌های داخلی (Inner Classes)

کلاس‌های داخلی در Kotlin با استفاده از کلمه کلیدی `inner` تعریف می‌شوند و به کلاس خارجی خود دسترسی دارند.

class Outer {
    val outerVar = "I am from Outer"

    inner class Inner {
        fun printOuterVar() {
            println(outerVar)
        }
    }
}

استفاده از کلاس‌های داخلی

fun main() {
    val outer = Outer()
    val inner = outer.Inner()
    inner.printOuterVar() // خروجی: I am from Outer
}

Comment

در زبان برنامه‌نویسی Kotlin، نظرات به عنوان توضیحاتی استفاده می‌شوند که به برنامه‌نویسان دیگر (و خود شما) کمک می‌کنند تا کد را بهتر درک کنند. این نظرات در زمان اجرای برنامه نادیده گرفته می‌شوند و تاثیری در عملکرد آن ندارند. Kotlin از دو نوع نظر (Comment) پشتیبانی می‌کند: نظرات تک‌خطی و نظرات چندخطی.

نظرات تک‌خطی (Single-line Comments)

نظرات تک‌خطی برای اضافه کردن توضیحات کوتاه و مختصر در کد استفاده می‌شوند. این نظرات با دو علامت اسلش `//` شروع می‌شوند و تا انتهای همان خط ادامه دارند. نظرات تک‌خطی معمولاً برای توضیح مختصر یک خط کد یا بخش خاصی از کد به کار می‌روند.

val name = "Ali" // تعریف متغیر نام
println(name) // نمایش نام در خروجی

در اینجا، هر دو `//` نظرات تک‌خطی هستند که بعد از آن‌ها توضیحاتی درباره‌ی عملکرد کد نوشته شده است. این توضیحات برای برنامه‌نویسان مفید هستند، ولی در زمان اجرای کد نادیده گرفته می‌شوند.

نظرات چندخطی (Multi-line Comments)

نظرات چندخطی زمانی استفاده می‌شوند که نیاز به توضیحات بلند و چندخطی برای کد داشته باشیم. این نوع نظرات با `/*` شروع و با `*/` پایان می‌یابند. هر چیزی که بین این دو علامت قرار گیرد، به عنوان نظر در نظر گرفته می‌شود و در زمان اجرا نادیده گرفته می‌شود.

/*
این بخش از کد، متغیر age را تعریف کرده و
سپس مقدار آن را نمایش می‌دهد.
*/
val age = 30
println(age)

در این مثال، نظر چندخطی توضیحاتی درباره‌ی عملکرد کلی این بخش از کد ارائه می‌دهد و شامل چندین خط است.

 نظرات تودرتو (Nested Comments)

یکی از قابلیت‌های خاص Kotlin، پشتیبانی از نظرات چندخطی تودرتو است. به این معنی که می‌توانید از `/* */` در داخل نظرات چندخطی دیگر استفاده کنید. این ویژگی به شما اجازه می‌دهد تا بخش‌های بزرگ‌تری از کد را موقتاً غیرفعال یا نظر کنید، حتی اگر آن بخش‌ها خودشان شامل نظرات چندخطی باشند.

/*
این بخش از کد، برخی محاسبات را انجام می‌دهد.
در اینجا می‌توان نظرات تودرتو هم استفاده کرد:
/*
این یک نظر تودرتو است که در داخل نظر چندخطی بزرگ‌تر قرار دارد.
*/
val result = 5 + 10
println(result)
*/

در این مثال، نظر چندخطی بیرونی شامل یک نظر چندخطی تودرتو است. این ویژگی به‌ویژه در زمان اشکال‌زدایی یا موقتاً غیرفعال کردن بخش‌هایی از کد مفید است.

کاربرد نظرات در Kotlin

– توضیح کد: برای توضیح عملکرد یک خط یا یک بخش از کد.
– اشکال‌زدایی: گاهی برای پیدا کردن باگ، می‌توان کد را موقتاً به صورت نظر درآورد تا بخش‌های دیگر را بررسی کنیم.
– مستندسازی: از نظرات برای نوشتن مستندات کد استفاده می‌شود، به خصوص در پروژه‌های بزرگ که نیاز است عملکرد بخش‌های مختلف به خوبی مشخص باشد.

نظرات داکیومنتیشن (Documentation Comments)

Kotlin از نوعی نظرات خاص برای مستندسازی کد به نام **نظرات داکیومنتیشن** نیز پشتیبانی می‌کند. این نظرات با `/**` شروع می‌شوند و معمولاً برای توضیح کلاس‌ها، توابع و پارامترها به کار می‌روند. در واقع، این نوع نظرات به‌طور خودکار مستندات تولید شده برای کد را تشکیل می‌دهند.

/**
 * این تابع نام کاربر را می‌گیرد و پیامی برای خوشامدگویی نمایش می‌دهد.
 *
 * @param name نام کاربر به عنوان یک رشته
 */
fun greetUser(name: String) {
    println("Welcome, $name!")
}

در این مثال، نظر داکیومنتیشن توضیحاتی در مورد تابع `greetUser` و پارامتر ورودی آن ارائه می‌دهد. این نظرات می‌توانند به صورت خودکار برای تولید مستندات کد استفاده شوند.

String Templates

در زبان برنامه‌نویسی Kotlin، قالب‌بندی رشته‌ها (String Templates) یکی از امکانات مفیدی است که به شما اجازه می‌دهد مقادیر متغیرها و عبارات را به راحتی درون یک رشته قرار دهید. این ویژگی باعث می‌شود که خواندن و نوشتن کد ساده‌تر و تمیزتر باشد.

قالب‌بندی ساده رشته‌ها با `$`

در Kotlin، می‌توان با استفاده از علامت `$`، مقدار یک متغیر را مستقیماً درون یک رشته قرار داد. به این صورت که با تایپ `$` قبل از نام متغیر، مقدار آن متغیر در رشته نمایش داده می‌شود.

val name = "Ali"
println("Hello, $name!")

خروجی:

Hello, Ali!

در این مثال، `$name` مقدار متغیر `name` را به درون رشته اضافه می‌کند.

 استفاده از عبارات در قالب‌بندی رشته‌ها

اگر نیاز داشته باشید از یک عبارت پیچیده‌تر استفاده کنید، می‌توانید از `${}` استفاده کنید. بین آکولادها `{}` می‌توان هر عبارتی را نوشت که سپس مقدارش در رشته قرار می‌گیرد.

val width = 10
val height = 5
println("The area of the rectangle is ${width * height}.")

خروجی:

The area of the rectangle is 50.

در اینجا، عبارت `${width * height}` محاسبه شده و مقدار آن در رشته نمایش داده می‌شود.

ترکیب متغیرها و عبارات در قالب‌بندی رشته‌ها

می‌توانید متغیرها و عبارات مختلفی را در یک رشته ترکیب کنید و با استفاده از `$` و `${}` آن‌ها را به کار ببرید.

val firstName = "Ali"
val lastName = "Rezaei"
val age = 30
println("Name: $firstName $lastName, Age: ${age + 1}")

خروجی:

Name: Ali Rezaei, Age: 31

 قالب‌بندی رشته‌های چند خطی (Multiline String Templates)

در Kotlin می‌توان رشته‌های چندخطی را با استفاده از `”””` تعریف کرد. این رشته‌ها که به آن‌ها **رشته‌های خام** (Raw Strings) هم می‌گویند، تمام محتوا را دقیقاً به همان صورتی که نوشته شده است نگه می‌دارند و نیاز به کاراکتر فرار (`\`) ندارند. می‌توانید از قالب‌بندی با `$` و `${}` در رشته‌های چندخطی نیز استفاده کنید.

val name = "Ali"
val age = 25
val description = """
    Name: $name
    Age: ${age + 5}
""".trimIndent()

println(description)

خروجی:

Name: Ali
Age: 30

در اینجا، از رشته چندخطی استفاده کرده‌ایم و همچنین از `${}` برای افزودن نتیجه محاسبه به رشته استفاده شده است.

 نکات مهم در قالب‌بندی رشته‌ها

– علامت `$` زمانی که درون رشته‌های معمولی استفاده می‌شود، نشان‌دهنده شروع یک متغیر یا عبارت است.
– اگر بخواهید خود علامت `$` را به عنوان یک کاراکتر در رشته نمایش دهید (بدون این‌که آن را به یک متغیر یا عبارت تبدیل کنید)، باید از `\$` استفاده کنید.

println("This is a dollar sign: \$")

خروجی:

This is a dollar sign: $

 استفاده از `String.format` برای قالب‌بندی پیچیده‌تر

اگر نیاز به قالب‌بندی‌های پیچیده‌تر دارید (مانند قالب‌بندی اعشاری یا قرار دادن کاراکترهای خاص)، می‌توانید از تابع `String.format` استفاده کنید که شبیه به قالب‌بندی رشته‌ها در زبان Java است.

val pi = 3.14159
val formattedString = String.format("Pi rounded to two decimal places is %.2f", pi)
println(formattedString)

خروجی:

Pi rounded to two decimal places is 3.14

در این مثال، از `%.2f` برای محدود کردن مقدار `pi` به دو رقم اعشار استفاده شده است.

عبارت شرطی if

عبارات شرطی `if` در Kotlin از پرکاربردترین ابزارها برای کنترل جریان برنامه هستند و به شما این امکان را می‌دهند که تصمیم‌گیری‌های مختلفی را بر اساس شرایط مشخص انجام دهید. در Kotlin، `if` می‌تواند به عنوان یک **عبارت** (Expression) نیز استفاده شود، به این معنا که می‌تواند مقداری را بازگرداند.

عبارت ساده `if`

یک ساختار ساده `if` زمانی استفاده می‌شود که بخواهید یک شرط خاص را بررسی کنید و در صورت درست بودن آن شرط، یک بلاک کد اجرا شود.

val number = 10
if (number > 0) {
    println("The number is positive.")
}

در این مثال، اگر مقدار `number` بزرگ‌تر از صفر باشد، پیام “The number is positive.” چاپ می‌شود.

ساختار `if-else`

در این ساختار، اگر شرط `if` برقرار نباشد، به صورت خودکار بلاک کد `else` اجرا می‌شود.

val number = -5
if (number > 0) {
    println("The number is positive.")
} else {
    println("The number is not positive.")
}

در اینجا، اگر مقدار `number` بزرگ‌تر از صفر نباشد، بلاک `else` اجرا شده و پیام “The number is not positive.” چاپ می‌شود.

ساختار `if-else if-else`

وقتی نیاز به بررسی چندین شرط مختلف دارید، می‌توانید از `if-else if-else` استفاده کنید. با این ساختار، تا زمانی که یکی از شرط‌ها برقرار شود، آن شرط اجرا می‌شود و باقی شرط‌ها نادیده گرفته می‌شوند.

val number = 0
if (number > 0) {
    println("The number is positive.")
} else if (number < 0) {
    println("The number is negative.")
} else {
    println("The number is zero.")
}

در این مثال، ابتدا شرط `if` بررسی می‌شود. اگر `number` بزرگ‌تر از صفر نباشد، شرط بعدی یعنی `else if` بررسی می‌شود. اگر هیچ کدام از شرایط برقرار نباشد، بلاک `else` اجرا خواهد شد.

استفاده از `if` به عنوان یک عبارت (Expression)

در Kotlin، می‌توانید از `if` به عنوان یک عبارت استفاده کنید، زیرا `if` یک **Expression** است. این بدان معناست که می‌توان مقدار بازگشتی از `if` را در یک متغیر ذخیره کرد یا به عنوان ورودی یک تابع استفاده نمود.

val number = 10
val result = if (number > 0) {
    "Positive"
} else {
    "Non-positive"
}

println("The number is $result")

در این مثال، مقدار `result` بر اساس نتیجه عبارت `if` تعیین می‌شود. اگر `number` مثبت باشد، مقدار `”Positive”` به `result` اختصاص داده می‌شود، در غیر این صورت مقدار `”Non-positive”` به آن اختصاص می‌یابد.

 نکته:
اگر از `if` به عنوان یک عبارت استفاده می‌کنید، مقدار نهایی بلاک `if` و `else` باید یکسان باشد تا نتیجه در متغیر ذخیره شود.

مثال کامل از `if` به عنوان Expression با محاسبات پیچیده

می‌توانید از `if` به عنوان یک Expression در محاسبات پیچیده‌تر استفاده کنید. در اینجا از `if` برای محاسبه قیمت بر اساس شرایط خاصی استفاده می‌کنیم.

val quantity = 20
val pricePerItem = 100
val discount = if (quantity > 10) {
    0.1 // 10% تخفیف
} else {
    0.0 // بدون تخفیف
}

val totalPrice = quantity * pricePerItem * (1 - discount)
println("Total price: $totalPrice")

در این مثال، اگر تعداد (`quantity`) بیشتر از 10 باشد، 10 درصد تخفیف اعمال می‌شود و قیمت کل محاسبه می‌شود.

استفاده از `if` بدون بلاک `else`

در Kotlin، می‌توان از `if` بدون `else` هم استفاده کرد، اما در این حالت `if` فقط یک دستور شرطی است و نمی‌تواند مقداری را بازگرداند. این یعنی `if` به تنهایی نمی‌تواند به عنوان Expression عمل کند.

val score = 85
if (score > 90) {
    println("Excellent")
} // اینجا نیازی به else نیست

در این مثال، فقط زمانی که شرط `if` برقرار باشد، پیام چاپ می‌شود و در غیر این صورت کدی اجرا نمی‌شود.

for loop

حلقه `for` در Kotlin یکی از ساختارهای کنترلی پرکاربرد برای تکرار مجموعه‌ای از دستورات است. از این حلقه می‌توان برای پیمایش در انواع داده‌هایی مانند لیست‌ها، آرایه‌ها، رشته‌ها و همچنین برای تکرار با استفاده از محدوده‌ها (`range`) استفاده کرد.

ساختار ساده حلقه `for`

در Kotlin، حلقه `for` به شکل زیر تعریف می‌شود:

for (item in collection) {
    // code to execute for each item
}

عبارت `(item in collection)` مشخص می‌کند که در هر تکرار، یک مقدار از مجموعه‌ی `collection` به `item` اختصاص داده می‌شود و کد داخل بلاک برای هر مقدار `item` اجرا می‌شود.

مثال:

val numbers = listOf(1, 2, 3, 4, 5)
for (number in numbers) {
    println(number)
}

در این مثال، حلقه برای هر عنصر در لیست `numbers` اجرا می‌شود و مقادیر `1، 2، 3، 4، 5` به ترتیب چاپ می‌شوند.

حلقه `for` با محدوده (`Range`)

در Kotlin می‌توانید از محدوده‌ها (`range`) برای تعیین محدوده‌ای از اعداد استفاده کنید. محدوده‌ها با استفاده از `..` تعریف می‌شوند.

مثال: محدوده صعودی

for (i in 1..5) {
    println(i)
}

خروجی:

1
2
3
4
5

در اینجا، حلقه `for` از `1` تا `5` تکرار می‌شود.

محدوده نزولی
برای تکرار به صورت نزولی، می‌توانید از `downTo` استفاده کنید.

for (i in 5 downTo 1) {
    println(i)
}

خروجی:

5
4
3
2
1

در این مثال، حلقه `for` از `5` به `1` به صورت نزولی تکرار می‌شود.

 تعیین گام (`step`) در حلقه `for`

می‌توانید از `step` برای تعیین گام‌های دلخواه در هر تکرار استفاده کنید. به عنوان مثال، می‌توان هر دو عدد یک بار حلقه را اجرا کرد.

مثال:

for (i in 1..10 step 2) {
    println(i)
}

خروجی:

1
3
5
7
9

در اینجا، `step` مقدار `2` است، بنابراین حلقه به صورت دو تا یک بار پیش می‌رود.

 پیمایش بر روی رشته‌ها

در Kotlin، می‌توانید از `for` برای پیمایش کاراکترهای یک رشته استفاده کنید.

val text = "Hello"
for (char in text) {
    println(char)
}

خروجی:

H
e
l
l
o

در اینجا، حلقه `for` برای هر کاراکتر در رشته `text` اجرا می‌شود و هر کاراکتر به صورت جداگانه چاپ می‌شود.

 پیمایش با استفاده از `withIndex`

با استفاده از تابع `withIndex`، می‌توانید هم به اندیس (index) و هم به مقدار عنصر دسترسی داشته باشید. این ویژگی مخصوصاً برای زمانی که نیاز به اطلاع از موقعیت عنصر در مجموعه دارید، مفید است.

val fruits = listOf("Apple", "Banana", "Cherry")
for ((index, fruit) in fruits.withIndex()) {
    println("Fruit at index $index is $fruit")
}

خروجی:

Fruit at index 0 is Apple
Fruit at index 1 is Banana
Fruit at index 2 is Cherry

در اینجا، از `withIndex` برای دسترسی به موقعیت و مقدار هر عنصر در لیست استفاده شده است.

حلقه‌های تو در تو (Nested Loops)

مانند بسیاری از زبان‌های برنامه‌نویسی دیگر، می‌توان در Kotlin نیز از حلقه‌های `for` تو در تو استفاده کرد.

for (i in 1..3) {
    for (j in 1..2) {
        println("i = $i, j = $j")
    }
}

خروجی:

i = 1, j = 1
i = 1, j = 2
i = 2, j = 1
i = 2, j = 2
i = 3, j = 1
i = 3, j = 2

در این مثال، یک حلقه `for` داخلی وجود دارد که برای هر مقدار از حلقه خارجی، کل حلقه داخلی را اجرا می‌کند.

 استفاده از حلقه `for` با آرایه‌ها

می‌توانید با حلقه `for` روی آرایه‌ها نیز پیمایش کنید.

val numbers = arrayOf(10, 20, 30)
for (num in numbers) {
    println(num)
}

در اینجا، حلقه `for` برای هر عنصر در آرایه `numbers` اجرا می‌شود و مقادیر آن چاپ می‌شوند.

خروج از حلقه با استفاده از `break` و `continue`

در Kotlin، می‌توانید از `break` برای خروج از حلقه و از `continue` برای رد کردن تکرار جاری و ادامه با تکرار بعدی استفاده کنید.

for (i in 1..5) {
    if (i == 3) break
    println(i)
}

خروجی:

1
2

در اینجا، وقتی `i` برابر با `3` می‌شود، `break` باعث می‌شود که حلقه به طور کامل متوقف شود.

`continue`:

for (i in 1..5) {
    if (i == 3) continue
    println(i)
}

خروجی:

1
2
4
5

در این مثال، وقتی `i` برابر با `3` می‌شود، `continue` باعث می‌شود که تکرار جاری رد شود و حلقه از تکرار بعدی ادامه پیدا کند.

while loop

حلقه `while` در Kotlin برای تکرار مجموعه‌ای از دستورات تا زمانی که یک شرط خاص برقرار باشد استفاده می‌شود. از این حلقه می‌توانید در مواردی استفاده کنید که تعداد تکرارها از پیش مشخص نیست و به وضعیت شرط وابسته است.

در Kotlin، دو نوع حلقه تکرار `while` و `do-while` وجود دارد.

 حلقه `while`

ساختار حلقه `while` به این صورت است که ابتدا شرط بررسی می‌شود و اگر شرط برقرار بود، کد داخل حلقه اجرا می‌شود. این تکرار تا زمانی که شرط برقرار باشد ادامه پیدا می‌کند.

ساختار کلی:

while (شرط) {
    // کدهایی که باید تکرار شوند
}

مثال ساده:

var counter = 1
while (counter <= 5) {
    println("Counter: $counter")
    counter++
}

خروجی:

Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5

در این مثال، مقدار `counter` از 1 شروع می‌شود و تا زمانی که مقدار آن کمتر یا مساوی 5 باشد، حلقه ادامه پیدا می‌کند. در هر تکرار، مقدار `counter` یک واحد افزایش می‌یابد.

حلقه `do-while`

حلقه `do-while` مشابه `while` است، اما تفاوت اصلی این است که کد داخل حلقه حداقل یک‌بار اجرا می‌شود، حتی اگر شرط برقرار نباشد. ابتدا کد داخل `do` اجرا می‌شود و سپس شرط `while` بررسی می‌شود. اگر شرط برقرار باشد، حلقه تکرار می‌شود.

ساختار کلی:

do {
    // کدهایی که باید تکرار شوند
} while (شرط)

مثال:

var counter = 1
do {
    println("Counter: $counter")
    counter++
} while (counter <= 5)

خروجی:

Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5

در اینجا، `do` یک بار اجرا می‌شود، و سپس شرط بررسی می‌شود. اگر شرط برقرار باشد، حلقه ادامه پیدا می‌کند.

تفاوت `while` و `do-while`

– در `while`، ابتدا شرط بررسی می‌شود و سپس کد اجرا می‌شود. بنابراین اگر شرط در ابتدا برقرار نباشد، کد حتی یک بار هم اجرا نخواهد شد.
– در `do-while`، کد داخل حلقه حداقل یک بار اجرا می‌شود و سپس شرط بررسی می‌شود.

مثال تفاوت:

var countWhile = 6
while (countWhile <= 5) {
    println("While Loop: $countWhile")
    countWhile++
}

var countDoWhile = 6
do {
    println("Do-While Loop: $countDoWhile")
    countDoWhile++
} while (countDoWhile <= 5)

خروجی:

Do-While Loop: 6

در این مثال، حلقه `while` اجرا نمی‌شود، زیرا شرط آن در ابتدا برقرار نیست. اما `do-while` یک بار اجرا می‌شود و مقدار `6` را چاپ می‌کند، حتی اگر شرط برقرار نباشد.

استفاده از `break` و `continue` در حلقه `while`

`break`: باعث می‌شود که حلقه به طور کامل متوقف شود.
`continue`: باعث می‌شود که اجرای تکرار جاری متوقف شده و حلقه به تکرار بعدی برود.

مثال `break` در `while`:

var i = 1
while (i <= 10) {
    if (i == 5) break
    println("Number: $i")
    i++
}

خروجی:

var i = 1
while (i <= 10) {
    if (i == 5) break
    println("Number: $i")
    i++
}

در این مثال، زمانی که `i` برابر با `5` شود، `break` باعث توقف کامل حلقه می‌شود.

مثال `continue` در `while`:

var i = 0
while (i < 5) {
    i++
    if (i == 3) continue
    println("Number: $i")
}

خروجی:

Number: 1
Number: 2
Number: 4
Number: 5

در این مثال، زمانی که `i` برابر با `3` می‌شود، `continue` باعث می‌شود که تکرار جاری نادیده گرفته شود و به تکرار بعدی برود. به همین دلیل مقدار `3` چاپ نمی‌شود.

حلقه‌های بی‌نهایت با `while`

اگر شرط `while` همیشه برقرار باشد، حلقه بی‌نهایت ایجاد می‌شود و اجرای برنامه به طور نامحدود ادامه پیدا می‌کند (مگر اینکه برنامه متوقف شود یا از `break` استفاده شود).

while (true) {
    println("This is an infinite loop")
    break // برای جلوگیری از حلقه بی‌نهایت
}

در این مثال، با استفاده از `break` حلقه بی‌نهایت متوقف می‌شود.

when expression

عبارت `when` در Kotlin یکی از ابزارهای پرکاربرد برای تصمیم‌گیری شرطی است و می‌تواند به عنوان جایگزینی برای `switch` در زبان‌های دیگر استفاده شود. `when` انعطاف‌پذیری و قابلیت‌های بیشتری نسبت به `switch` دارد و به شما این امکان را می‌دهد که بر اساس مقادیر و شرایط مختلف، کدهای متفاوتی را اجرا کنید.

 ساختار کلی `when`

عبارت `when` با مقدار یا متغیری که می‌خواهید بررسی کنید آغاز می‌شود و سپس شرایط مختلف در قالب caseهایی تعریف می‌شوند که در صورت مطابقت با مقدار اولیه، اجرا می‌شوند.

when (expression) {
    value1 -> {
        // کد برای زمانی که expression برابر با value1 است
    }
    value2 -> {
        // کد برای زمانی که expression برابر با value2 است
    }
    else -> {
        // کد برای زمانی که هیچ کدام از شرایط بالا برقرار نیست
    }
}

استفاده ساده از `when`

در اینجا، `when` بر اساس مقدار `day` تصمیم‌گیری می‌کند:

val day = 3
val dayName = when (day) {
    1 -> "Monday"
    2 -> "Tuesday"
    3 -> "Wednesday"
    4 -> "Thursday"
    5 -> "Friday"
    6 -> "Saturday"
    7 -> "Sunday"
    else -> "Invalid day"
}
println(dayName)

خروجی:

Wednesday

در این مثال، مقدار `day` برابر با `3` است و بنابراین `when` مقدار `”Wednesday”` را برمی‌گرداند. اگر هیچ کدام از شرایط برقرار نباشند، بخش `else` اجرا می‌شود.

بررسی چندین مقدار در یک case

در Kotlin، می‌توانید چند مقدار را در یک case با استفاده از کاما (`,`) تعریف کنید.

مثال:

val number = 3
val result = when (number) {
    1, 3, 5, 7, 9 -> "Odd number"
    2, 4, 6, 8, 10 -> "Even number"
    else -> "Unknown number"
}
println(result)

خروجی:

Odd number

در اینجا، اگر مقدار `number` یکی از اعداد `1، 3، 5، 7 یا 9` باشد، `”Odd number”` چاپ می‌شود.

استفاده از محدوده‌ها در `when`

می‌توانید از محدوده‌ها (`range`) برای بررسی اینکه آیا مقدار در یک بازه مشخص قرار دارد یا خیر استفاده کنید.

#### مثال:

val score = 85
val grade = when (score) {
    in 90..100 -> "A"
    in 80..89 -> "B"
    in 70..79 -> "C"
    in 60..69 -> "D"
    else -> "F"
}
println(grade)

خروجی:

B

در اینجا، `score` در محدوده `80..89` قرار دارد، بنابراین مقدار `”B”` به `grade` اختصاص داده می‌شود.

بررسی شرایط پیچیده‌تر در `when`

عبارت `when` می‌تواند شامل شرایط پیچیده‌تر با استفاده از توابع و عبارات منطقی باشد.

مثال:

val x = 10
val y = 5
val result = when {
    x > y -> "x is greater than y"
    x < y -> "x is less than y"
    else -> "x is equal to y"
}
println(result)

خروجی:

x is greater than y

در این مثال، از `when` بدون آرگومان استفاده شده و هر شرط به صورت جداگانه بررسی می‌شود.

استفاده از `when` به عنوان Expression

در Kotlin، `when` می‌تواند به عنوان یک Expression استفاده شود و مقداری را برگرداند. این مقدار می‌تواند در یک متغیر ذخیره شود یا به عنوان ورودی به یک تابع ارسال شود.

مثال:

val age = 18
val category = when (age) {
    in 0..12 -> "Child"
    in 13..19 -> "Teenager"
    in 20..59 -> "Adult"
    else -> "Senior"
}
println("Age category: $category")

خروجی:

Age category: Teenager

در اینجا، `when` به عنوان یک Expression استفاده شده و مقدار `”Teenager”` به `category` اختصاص داده شده است.

استفاده از `is` در `when` برای بررسی نوع داده

عبارت `when` به شما اجازه می‌دهد نوع داده را با استفاده از `is` بررسی کنید که برای کار با انواع مختلف داده بسیار مفید است.

مثال:

fun checkType(obj: Any) {
    when (obj) {
        is String -> println("It is a String with length ${obj.length}")
        is Int -> println("It is an Integer with value $obj")
        is Boolean -> println("It is a Boolean with value $obj")
        else -> println("Unknown type")
    }
}

checkType("Hello")
checkType(123)
checkType(true)

خروجی:

It is a String with length 5
It is an Integer with value 123
It is a Boolean with value true

در این مثال، `when` نوع داده ورودی را بررسی کرده و بر اساس نوع داده، پیام مناسب را چاپ می‌کند.

 استفاده از `when` بدون `else`

در صورتی که `when` تمام شرایط ممکن را پوشش دهد، استفاده از `else` اختیاری است. اگر تمام مقادیر ممکن برای یک نوع داده بررسی شوند، نیازی به `else` نیست.

مثال:

val direction = "NORTH"
val message = when (direction) {
    "NORTH" -> "Moving North"
    "SOUTH" -> "Moving South"
    "EAST" -> "Moving East"
    "WEST" -> "Moving West"
    else -> "Invalid direction"
}
println(message)

در این مثال، چون تمامی جهت‌ها بررسی شده‌اند، استفاده از `else` اختیاری است؛ اما اگر مقدار غیرمنتظره‌ای مانند `”UP”` وارد شود، `else` می‌تواند برای مدیریت آن استفاده شود.

تعریف محدوده (Range)

در Kotlin، می‌توان از عملگر `in` برای بررسی این که آیا یک مقدار در محدوده‌ی مشخصی قرار دارد یا خیر استفاده کرد. این قابلیت باعث می‌شود تا کد خواناتر و ساده‌تر شود.

یک محدوده در Kotlin می‌تواند با استفاده از عملگر `..` تعریف شود که شروع و پایان محدوده را مشخص می‌کند. همچنین محدوده‌ها در Kotlin شامل مقدار شروع و مقدار پایان هستند، به این معنی که هر دو مقدار ابتدا و انتها در محدوده قرار می‌گیرند.

مثال ساده:

val range = 1..10

در اینجا، `range` یک محدوده از اعداد `1` تا `10` است.

بررسی مقدار در محدوده با استفاده از `in`

برای بررسی اینکه آیا یک عدد در محدوده خاصی قرار دارد یا خیر، می‌توانید از عملگر `in` استفاده کنید.

مثال:

val number = 5
if (number in 1..10) {
    println("The number is in the range")
} else {
    println("The number is out of range")
}

خروجی:

The number is in the range

در این مثال، `number` در محدوده `1..10` قرار دارد، بنابراین شرط `if` برقرار است و پیام مناسب چاپ می‌شود.

استفاده از `!in` برای بررسی خارج از محدوده

اگر بخواهید بررسی کنید که یک عدد **خارج** از محدوده خاصی است، می‌توانید از عملگر `!in` استفاده کنید.

مثال:

val number = 15
if (number !in 1..10) {
    println("The number is out of range")
} else {
    println("The number is in the range")
}

خروجی:

The number is out of range

در اینجا، `number` خارج از محدوده `1..10` قرار دارد، بنابراین شرط برقرار است و پیام مربوطه چاپ می‌شود.

استفاده از محدوده‌ها در عبارات `when`

یکی دیگر از کاربردهای محدوده‌ها در Kotlin، استفاده از آن‌ها در عبارات `when` است. این کار به شما اجازه می‌دهد که مقادیر مختلف را با محدوده‌ها در `when` تطابق دهید.

مثال:

val score = 85
val grade = when (score) {
    in 90..100 -> "A"
    in 80..89 -> "B"
    in 70..79 -> "C"
    in 60..69 -> "D"
    else -> "F"
}
println("Grade: $grade")

خروجی:

Grade: B

در اینجا، `score` در محدوده `80..89` قرار دارد و به همین دلیل مقدار `”B”` به `grade` اختصاص داده می‌شود.

 محدوده‌های نزولی با `downTo`

علاوه بر محدوده‌های صعودی، می‌توانید محدوده‌های نزولی نیز با استفاده از `downTo` تعریف کنید. این نوع محدوده از مقدار شروع به مقدار پایان به صورت نزولی حرکت می‌کند.

مثال:

val number = 3
if (number in 5 downTo 1) {
    println("The number is in the descending range")
} else {
    println("The number is out of range")
}

خروجی:

The number is in the descending range

در این مثال، محدوده از `5` به `1` به صورت نزولی تعریف شده و چون `number` در این محدوده قرار دارد، پیام مربوطه چاپ می‌شود.

 استفاده از `step` در محدوده‌ها

با `step` می‌توانید گام‌های دلخواهی برای پیمایش در محدوده‌ها مشخص کنید.

مثال:

for (i in 1..10 step 2) {
    println(i)
}

خروجی:

1
3
5
7
9

در اینجا، محدوده `1..10` با گام‌های `2` پیمایش می‌شود، بنابراین فقط اعداد فرد چاپ می‌شوند.

Collections

در Kotlin، برای تکرار (iterate) روی مجموعه‌ها مانند لیست‌ها، آرایه‌ها، مجموعه‌ها (sets) و نقشه‌ها (maps)، چندین روش و ابزار مختلف وجود دارد. این روش‌ها به شما این امکان را می‌دهند که به سادگی روی عناصر مجموعه‌های مختلف پیمایش کنید و عملیات مختلفی را انجام دهید.

استفاده از حلقه `for` برای تکرار روی مجموعه‌ها

تکرار روی لیست‌ها یا آرایه‌ها

یکی از ساده‌ترین راه‌ها برای تکرار روی یک مجموعه در Kotlin استفاده از حلقه `for` است. شما می‌توانید با استفاده از این حلقه به راحتی روی تمام عناصر یک لیست یا آرایه پیمایش کنید.

مثال تکرار روی لیست:

val fruits = listOf("Apple", "Banana", "Cherry")
for (fruit in fruits) {
    println(fruit)
}

خروجی:

Apple
Banana
Cherry

در این مثال، با استفاده از حلقه `for` روی لیست `fruits` پیمایش شده و هر عنصر درون لیست به صورت متوالی چاپ می‌شود.

مثال تکرار روی آرایه:

val numbers = arrayOf(1, 2, 3, 4, 5)
for (number in numbers) {
    println(number)
}

خروجی:

1
2
3
4
5

 استفاده از `indices` برای دسترسی به ایندکس‌ها

گاهی اوقات ممکن است بخواهید علاوه بر خود عنصر، به ایندکس (شاخص) آن هم دسترسی داشته باشید. برای این کار می‌توانید از ویژگی `indices` در Kotlin استفاده کنید.

مثال:

val fruits = listOf("Apple", "Banana", "Cherry")
for (index in fruits.indices) {
    println("Index: $index, Fruit: ${fruits[index]}")
}

خروجی:

Index: 0, Fruit: Apple
Index: 1, Fruit: Banana
Index: 2, Fruit: Cherry

در اینجا، `fruits.indices` محدوده‌ای از ایندکس‌های لیست را فراهم می‌کند که می‌توانید به راحتی به هر عنصر و ایندکس آن دسترسی پیدا کنید.

 استفاده از `forEach` برای تکرار

Kotlin همچنین یک روش کاربردی دیگر به نام `forEach` ارائه می‌دهد که به شما این امکان را می‌دهد که به صورت تابعی روی عناصر مجموعه پیمایش کنید. این روش معمولاً در مواقعی که می‌خواهید از برنامه‌نویسی تابعی استفاده کنید مفید است.

مثال:

val fruits = listOf("Apple", "Banana", "Cherry")
fruits.forEach { fruit ->
    println(fruit)
}

خروجی:

Apple
Banana
Cherry

در اینجا، `forEach` یک تابع است که به هر عنصر از مجموعه یک پارامتر می‌دهد (در این مثال پارامتر `fruit`) و در داخل بلوک کد آن می‌توانید عملیاتی مانند چاپ انجام دهید.

استفاده از `while` برای تکرار

اگر بخواهید از یک حلقه `while` برای تکرار روی مجموعه استفاده کنید، می‌توانید از اندیس‌ها یا اشاره‌گرها استفاده کنید.

مثال:

val fruits = listOf("Apple", "Banana", "Cherry")
var index = 0
while (index < fruits.size) {
    println(fruits[index])
    index++
}

خروجی:

Apple
Banana
Cherry

در اینجا از یک حلقه `while` برای تکرار روی ایندکس‌های لیست استفاده شده است.

تکرار روی مجموعه‌ها (Sets)

در Kotlin، مجموعه‌ها (`Set`) هم مانند لیست‌ها و آرایه‌ها قابلیت تکرار دارند. از آنجایی که مجموعه‌ها ترتیب خاصی ندارند، این تکرار به صورت تصادفی انجام می‌شود.

مثال:

val uniqueFruits = setOf("Apple", "Banana", "Cherry", "Banana")
for (fruit in uniqueFruits) {
    println(fruit)
}

خروجی:

Apple
Banana
Cherry

در اینجا، تکرار روی یک مجموعه `Set` انجام شده است که دارای عناصر منحصر به فرد است.

تکرار روی نقشه‌ها (Maps)

در Kotlin، شما می‌توانید روی نقشه‌ها (که مجموعه‌ای از جفت‌های کلید-مقدار هستند) نیز تکرار کنید. برای این کار، می‌توانید از `for` یا `forEach` استفاده کنید.

استفاده از `for` برای تکرار روی نقشه‌ها

برای تکرار روی یک نقشه و دسترسی به هر کلید و مقدار، می‌توانید از حلقه `for` استفاده کنید.

مثال:

val fruitPrices = mapOf("Apple" to 2, "Banana" to 1, "Cherry" to 3)
for ((fruit, price) in fruitPrices) {
    println("$fruit costs $price")
}

خروجی:

Apple costs 2
Banana costs 1
Cherry costs 3

در اینجا، از یک عبارت destructuring برای استخراج همزمان کلید و مقدار در هر تکرار استفاده شده است.

استفاده از `forEach` برای تکرار روی نقشه‌ها

همچنین می‌توانید از `forEach` برای تکرار روی نقشه‌ها استفاده کنید.

مثال:

val fruitPrices = mapOf("Apple" to 2, "Banana" to 1, "Cherry" to 3)
fruitPrices.forEach { (fruit, price) ->
    println("$fruit costs $price")
}

خروجی:

Apple costs 2
Banana costs 1
Cherry costs 3

در اینجا نیز همانند مثال قبلی، با استفاده از `forEach` و destructuring، به هر جفت کلید-مقدار دسترسی پیدا کرده و عملیات مورد نظر را انجام می‌دهیم.

استفاده از `map` برای تکرار و تبدیل مجموعه‌ها

در Kotlin می‌توانید از `map` برای تبدیل مجموعه‌ها در هنگام تکرار استفاده کنید. این روش مجموعه‌ای جدید ایجاد می‌کند که در آن هر عنصر مجموعه اصلی به یک مقدار جدید تبدیل شده است.

مثال:

val numbers = listOf(1, 2, 3, 4)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers)  // [1, 4, 9, 16]

در اینجا، با استفاده از `map` هر عدد به مربع خود تبدیل شده است.

 نتیجه‌گیری

در Kotlin، تکرار روی مجموعه‌ها از جمله لیست‌ها، آرایه‌ها، مجموعه‌ها و نقشه‌ها به راحتی با استفاده از ساختارهای مختلفی مانند `for`, `forEach`, `while`, و روش‌های توابعی مانند `map` انجام می‌شود. این امکانات به شما این امکان را می‌دهند که بدون نگرانی از پیچیدگی‌های ساختاری، روی مجموعه‌های مختلف پیمایش کرده و عملیات مورد نظر خود را انجام دهید.

Nullable values and null checks

در Kotlin، یکی از ویژگی‌های کلیدی این زبان، سیستم تایپ ایمن است که به وضوح نوع‌های `nullable` و `non-nullable` را از هم تفکیک می‌کند. در Kotlin، به طور پیش‌فرض، تمام متغیرها و پارامترها از نوع `non-nullable` هستند، به این معنا که نمی‌توانند مقدار تهی (null) را بپذیرند. اما زمانی که شما می‌خواهید یک متغیر یا پارامتر بتواند مقدار تهی بپذیرد، باید به‌طور صریح آن را به عنوان `nullable` علامت‌گذاری کنید.

علامت‌گذاری یک نوع به عنوان nullable

برای علامت‌گذاری یک نوع به عنوان nullable، کافی است که علامت `?` را در انتهای نام نوع قرار دهید. این علامت نشان می‌دهد که متغیر یا پارامتر می‌تواند مقدار `null` را بپذیرد.

مثال:

var name: String? = null

در اینجا، نوع `String?` نشان‌دهنده این است که متغیر `name` می‌تواند مقدار تهی (null) یا یک رشته (`String`) را نگهداری کند.

استفاده از انواع nullable

در Kotlin، وقتی یک نوع به عنوان `nullable` مشخص می‌شود، می‌توانید آن را با مقدار `null` مقداردهی کنید یا بررسی کنید که آیا آن مقدار `null` است یا نه.

مثال:

var name: String? = "Kotlin"
name = null  // این مجاز است

 

در این مثال، متغیر `name` ابتدا یک رشته `”Kotlin”` دارد، ولی می‌تواند به مقدار `null` هم تغییر یابد چون نوع آن `String?` است که نشان‌دهنده `nullable` بودن است.

 بررسی اینکه آیا یک مقدار `null` است

برای بررسی اینکه آیا یک متغیر `nullable` برابر با `null` است یا نه، می‌توانید از عملگر `==` یا دستور `if` استفاده کنید.

مثال:

var name: String? = null
if (name == null) {
    println("Name is null")
} else {
    println("Name is not null")
}

خروجی:

Name is null

 استفاده از `?.` برای دسترسی به مقادیر nullable

اگر می‌خواهید به اعضای یک متغیر `nullable` دسترسی داشته باشید، باید از عملگر `?.` استفاده کنید. این عملگر به شما اجازه می‌دهد تا در صورتی که متغیر `null` باشد، بدون بروز خطا، عملیات را انجام دهید.

مثال:

var name: String? = "Kotlin"
println(name?.length)  // این مقدار 6 را چاپ می‌کند

name = null
println(name?.length)  // این مقدار null را چاپ می‌کند و خطا نمی‌دهد

در اینجا، وقتی متغیر `name` مقدار `null` دارد، عملگر `?.` به شما این امکان را می‌دهد که از بروز خطا جلوگیری کنید و به جای آن، مقدار `null` را برگردانید.

 استفاده از `?:` (الگوی Elvish) برای مقداردهی پیش‌فرض

اگر متغیر `nullable` شما مقدار `null` داشته باشد و بخواهید یک مقدار پیش‌فرض برای آن تعیین کنید، می‌توانید از عملگر `?:` استفاده کنید. این عملگر به شما این امکان را می‌دهد که مقدار پیش‌فرضی را در صورتی که متغیر `null` باشد، تعیین کنید.

مثال:

var name: String? = null
val length = name?.length ?: 0  // اگر name null باشد، 0 به عنوان مقدار پیش‌فرض استفاده می‌شود
println(length)  // 0

در اینجا، اگر متغیر `name` مقدار `null` باشد، به جای دسترسی به `length`، مقدار پیش‌فرض `0` بازگردانده می‌شود.

 استفاده از `!!` برای اعمال غیرقابل قبول بودن null

گاهی اوقات ممکن است مطمئن باشید که یک متغیر `nullable` هرگز `null` نخواهد بود، اما در صورتی که این متغیر مقدار `null` داشته باشد، خطا ایجاد شود. در این مواقع، می‌توانید از عملگر `!!` برای اطمینان از غیر-null بودن متغیر استفاده کنید. این عملگر باعث می‌شود اگر متغیر `null` باشد، یک استثنا (`NullPointerException`) ایجاد شود.

مثال:

var name: String? = "Kotlin"
println(name!!.length)  // مقدار 6 را چاپ می‌کند

name = null
println(name!!.length)  // اینجا NullPointerException پرتاب می‌شود

 تغییر متغیر nullable به non-nullable

اگر مطمئن هستید که یک متغیر `nullable` هیچ‌گاه مقدار `null` نخواهد داشت (مثلاً پس از یک چک در کد خود)، می‌توانید از `!!` استفاده کنید تا آن را به نوع `non-nullable` تبدیل کنید. این کار با تبدیل امن انجام می‌شود.

مثال:

var name: String? = "Kotlin"
val length: Int = name!!.length  // این مجاز است

اما اگر `name` مقدار `null` داشته باشد، یک استثنا پرتاب خواهد شد.

 خلاصه تفاوت‌ها میان `nullable` و `non-nullable`

-Non-nullable: به طور پیش‌فرض، در Kotlin، تمام متغیرها از نوع غیر nullable هستند. یعنی نمی‌توانند مقدار `null` را نگهداری کنند.
– مثال: `var name: String = “Kotlin”`

– Nullable: برای اینکه یک متغیر یا پارامتر بتواند مقدار `null` را بپذیرد، باید نوع آن را به‌طور صریح به `nullable` تبدیل کنید، که با قرار دادن علامت `?` در انتهای نوع انجام می‌شود.
– مثال: `var name: String? = null`

Type checks and automatic casts

در Kotlin، عملگر `is` برای بررسی این‌که آیا یک شیء نمونه‌ای از یک نوع خاص است یا خیر، استفاده می‌شود. این عملگر به شما این امکان را می‌دهد که در زمان اجرا بررسی کنید که آیا یک متغیر از نوع خاصی است یا نه. علاوه بر این، Kotlin ویژگی ریخته‌گری خودکار (Smart Cast) را فراهم می‌کند که به شما این امکان را می‌دهد که نیازی به استفاده از عملگر `as` برای تبدیل نوع نداشته باشید، اگر قبل از آن تایپ شیء توسط عملگر `is` تأیید شده باشد.

استفاده از عملگر `is` برای بررسی نوع

عملگر `is` در Kotlin برای بررسی اینکه آیا یک شیء از نوع خاصی است، استفاده می‌شود. وقتی یک شیء با استفاده از `is` بررسی می‌شود، نتیجه یک مقدار بولی (`true` یا `false`) است که نشان می‌دهد آیا شیء مورد نظر نمونه‌ای از نوع مشخص شده است یا نه.

مثال:

val name: Any = "Kotlin"
if (name is String) {
    println("The name is a String")
} else {
    println("The name is not a String")
}

خروجی:

The name is a String

در اینجا، عملگر `is` بررسی می‌کند که آیا متغیر `name` از نوع `String` است یا خیر. چون مقدار آن یک رشته است، خروجی `true` است و پیام “The name is a String” چاپ می‌شود.

 ریخته‌گری خودکار (Smart Cast)

یکی از ویژگی‌های مهم Kotlin، ریخته‌گری خودکار (Smart Cast) است. هنگامی که با استفاده از عملگر `is` تایید می‌کنید که یک شیء از نوع خاصی است، Kotlin به طور خودکار آن شیء را به نوع مورد نظر تبدیل می‌کند و شما نیازی به استفاده از عملگر `as` برای تبدیل نوع ندارید. این ویژگی باعث کاهش تعداد تبدیل‌های دستی نوع در کد می‌شود و کد را تمیزتر و ایمن‌تر می‌کند.

مثال بدون نیاز به `as`:

fun printLength(obj: Any) {
    if (obj is String) {
        // بدون نیاز به 'as' برای تبدیل
        println("The length of the string is: ${obj.length}")
    } else {
        println("Not a string")
    }
}

val str = "Hello"
printLength(str)  // خروجی: The length of the string is: 5

در اینجا، وقتی از `is String` استفاده می‌کنیم، Kotlin به طور خودکار شیء `obj` را به نوع `String` تبدیل می‌کند، بنابراین نیازی به انجام تبدیل دستی (`obj as String`) نیست. پس می‌توانیم مستقیماً به ویژگی `length` دسترسی پیدا کنیم.

استفاده از `is` در عبارات `when`

عملگر `is` می‌تواند در عبارات `when` نیز استفاده شود، که این قابلیت به شما این امکان را می‌دهد که به راحتی بررسی کنید که آیا یک شیء نمونه‌ای از یک نوع خاص است یا خیر و عملیات مختلفی را انجام دهید.

مثال:

fun describe(obj: Any): String {
    return when (obj) {
        is Int -> "Integer"
        is String -> "String"
        is Double -> "Double"
        else -> "Unknown"
    }
}

val description = describe("Kotlin")
println(description)  // خروجی: String

در اینجا، در عبارت `when`، عملگر `is` برای بررسی نوع متغیر `obj` استفاده می‌شود. بسته به نوع، متن مناسب برگردانده می‌شود.

بررسی نوع و استفاده از متغیرهای تغییرناپذیر

در Kotlin، وقتی که یک متغیر تغییرناپذیر (با استفاده از `val`) از یک نوع خاص چک شود، پس از تایید نوع با استفاده از `is`، نیازی به ارسال صریح نوع برای آن متغیر نیست. Kotlin به طور خودکار تبدیل‌های لازم را انجام می‌دهد.

مثال:

val obj: Any = "Kotlin"

if (obj is String) {
    // در اینجا obj به طور خودکار به نوع String تبدیل می‌شود
    println(obj.length)  // مقدار: 6
}

در اینجا، پس از استفاده از `obj is String`، نوع `obj` به طور خودکار به `String` تبدیل می‌شود و می‌توانیم به ویژگی‌های خاص این نوع (مانند `length`) دسترسی پیدا کنیم بدون این که نیاز به استفاده از تبدیل صریح `as` داشته باشیم.

استفاده از `is` با انواع خاص

عملگر `is` می‌تواند برای بررسی انواع خاص در انواع پیچیده‌تر مانند کلاس‌های سفارشی یا انواع بازگشتی از توابع هم استفاده شود.

مثال با یک کلاس سفارشی:

open class Animal
class Dog : Animal()
class Cat : Animal()

fun checkAnimal(animal: Animal) {
    if (animal is Dog) {
        println("This is a dog")
    } else if (animal is Cat) {
        println("This is a cat")
    } else {
        println("Unknown animal")
    }
}

val animal: Animal = Dog()
checkAnimal(animal)  // خروجی: This is a dog

در اینجا، با استفاده از عملگر `is`, می‌توانیم بررسی کنیم که شیء از کدام کلاس مشتق شده است (در اینجا `Dog` یا `Cat`).

آموزش سینتکس های پایه

دیدگاه های شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *