سوالات مصاحبه‌ی استخدامی کاتلین همراه با جواب(قسمت چهارم)

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

 

 

“ما را در اینستاگرام دنبال کنید”

در این مقاله از سری مقالات برنامه نویسی اندروید می خواهیم شما را با چند تا از مهم ترین سوالاتی که ممکن است در روز مصاحبه‌ی استخدامی کاتلین از شما پرسیده شود آشنا کنیم. پس با سایت ترولرن همراه باش.

“قبل از شروع مقاله، بگم که بعد از مطالعه این مطلب، از آموزش پروژه محور برنامه نویسی اندروید سایتمون یعنی دوره ژنرال اندروید غافل نشید.”

توی اون دوره 0 تا 100 کاتلین رو براتون شرح دادیم و دوتا پروژه خیلی خفن رو باهاش انجام دادیم.

اگه میخوای توی همه مصاحبه‌های استخدامی موفق باشی دوره ژنرال بهترین راهه…

1. در مورد Lambda expressions (عبارت‌های لامبدا) توضیح دهید.

Lambda expressions (عبارت‌های لامبدا) در کاتلین یک ویژگی قدرتمند هستند که به شما این امکان را می‌دهند تا توابع کوچک و مختصر را به سادگی تعریف کنید. این عبارات به شما اجازه می‌دهند که بخشی از کد خود را به صورت خلاصه و کوتاهتر ارائه دهید.

  • عناصر اصلی عبارات لامبدا در کاتلین

تعریف عبارت لامبدا:

عبارات لامبدا با استفاده از نماد “->” تعریف می‌شوند.
سینتکس کلی: (پارامترها) -> بدنه_تابع

مثال:

val sum: (Int, Int) -> Int = { x, y -> x + y }
println(sum(2, 3)) // خروجی: 5

استفاده از عبارات لامبدا به عنوان پارامترها:

می‌توانید عبارات لامبدا را به عنوان پارامترها به توابع دیگر ارسال کنید.

مثال:

val numbers = listOf(1, 2, 3, 4, 5)
val squared = numbers.map { it * it }
println(squared) // خروجی: [1, 4, 9, 16, 25]

استفاده از عبارات لامبدا به عنوان بلوک‌ها (بلوک لامبدا):

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

مثال:

val multiply: (Int, Int) -> Int = { x, y ->  
  val result = x * y 
   result + 10
}
println(multiply(4, 5)) // خروجی: 30

نقل متغیرها به داخل عبارات لامبدا (Closures):عبارات لامبدا می‌توانند به صورت خودکار متغیرهای اطراف خود (متغیرهای نقلی) را به عنوان فراپارامترها به تابع‌های خود در داخل برنامه‌نویسی نقل دهند.

مثال:

val outsideValue = 10
val addOutside: (Int) -> Int = { x -> x + outsideValue }
println(addOutside(5)) // خروجی: 15

Lambda expressions به شما این امکان را می‌دهند که کدهای کوچکتر و خواناتری ایجاد کنید، به ویژه زمانی که نیاز به ارسال توابع به عنوان پارامتر یا بازگشتی دارید. این ویژگی بهبود قابلیت خوانایی و انعطاف‌پذیری کد شما را افزایش می‌دهد.

2. primary constructor و init block در کاتلین.

یکی از سوالات مصاحبه‌ی استخدامی کاتلین در مورد primary constructor و init block در کاتلین است.

در کاتلین، کلاس‌ها می‌توانند یک کانستراکتور اصلی (primary constructor) و یک یا چند بلاک init داشته باشند. اینها به شما امکان انجام عملیات اولیه و ابتدایی بر روی ویژگی‌ها (پارامترها) و یا اجرای کدی که باید همواره در هنگام ایجاد یک نمونه از کلاس انجام شود را می‌دهند.

  • Primary Constructor

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

class MyClass(primaryParam: Int) {    // ...}

اگر در کلاس فقط یک کانستراکتور اصلی وجود داشته باشد و بدون هیچ init بلاکی، می‌توانید پارامترها را مستقیماً در خط تعریف کلاس قرار دهید.

class MyClass(val primaryParam: Int) {    // ...}
  • Init Block

بلاک init یک بلاک کد است که بلافاصله پس از اجرای کانستراکتور اصلی اجرا می‌شود. این بلاک به شما اجازه انجام عملیات پیچیده‌تر و ابتدایی را فراهم می‌کند.

class MyClass(val primaryParam: Int) { 
   init {    
    // کدی که هنگام ایجاد نمونه از کلاس اجرا می‌شود 
   }
}

بیشتر از یک بلاک init در یک کلاس می‌تواند وجود داشته باشد:

class MyClass(val primaryParam: Int) {  
  init {   
     // بلاک init اولیه   
 }
    init {  
      // بلاک init دوم  
  }
}

همچنین، می‌توانید در تعریف یک ویژگی (property) نیز از بلاک init استفاده کنید:

class MyClass(val primaryParam: Int) {  
  val calculatedProperty: Int
  init {    
    calculatedProperty = primaryParam * 2    
 }
}

در اینجا، مقدار calculatedProperty هنگام اجرای init محاسبه و تنظیم می‌شود.

3. secondary constructor در کاتلین و فرق آن با primary constructor

در کاتلین، هر کلاس می‌تواند یک یا چند constructor داشته باشد. Constructor اصلی (primary constructor) معمولاً در همان تعریف اولیه کلاس در کاتلین قرار می‌گیرد. اما گاهی اوقات نیاز است که یک کلاس دارای constructor دیگری باشد. این constructorهای اضافی به عنوان secondary constructor شناخته می‌شوند.

  • فرق اصلی میان primary constructor و secondary constructor در موارد زیر قابل ذکر است:

1. مکان تعریف

Primary constructor در تعریف اصلی کلاس ذکر می‌شود و بیشتر اطلاعات مربوط به متغیرها و پارامترهای ورودی کلاس را تعیین می‌کند. Secondary constructor در بلوک constructor جداگانه تعریف می‌شود و معمولاً برای موارد خاصی مانند ایجاد یک نمونه از کلاس با ورودی‌های مختلف یا انجام عملیات خاص به کار می‌رود.

2. استفاده از کلمه کلیدی constructor

Primary constructor از کلمه کلیدی constructor در تعریف اصلی کلاس استفاده نمی‌کند. Secondary constructor برای تعریف اضافی از کلمه کلیدی constructor به همراه پارامترها استفاده می‌کند.

مثال:

class Person(val name: String, val age: Int) { // Primary constructor 
   // ...
   // Secondary constructor 
   constructor(name: String) : this(name, 0) {
        // Additional initialization if needed  
  }
}

برای توضیح بیشتر، بیایید مثال دیگری را در نظر بگیریم:

class Car(val brand: String, val model: String, val year: Int) {    // Primary constructor
    init {   
     println("Initializing a Car object with brand: $brand, model: $model, year: $year")  
  }
  // Secondary constructor  
  constructor(brand: String, model: String) : this(brand, model, 0) {   
     println("Secondary constructor called")  
  }
}
fun main() {   
 val car1 = Car("Toyota", "Camry", 2022) 
 val car2 = Car("Honda", "Accord")
 // Output:
 // Initializing a Car object with brand: Toyota, model: Camry, year: 2022  
 // Initializing a Car object with brand: Honda, model: Accord, year: 0  
 // Secondary constructor called}

در این مثال، constructor اصلی اطلاعات اصلی خود را از طریق پارامترهای brand، model و year دریافت می‌کند. همچنین یک بلوک init برای اجرای کدهای مربوط به مقداردهی اولیه اضافی اضافه شده است.
سپس یک secondary constructor با دو پارامتر brand و model تعریف شده است. این secondary constructor با استفاده از this(brand, model, 0) به constructor اصلی متصل شده و مقدار year را به صورت پیش‌فرض برابر با 0 قرار می‌دهد. همچنین در داخل بدنه secondary constructor یک پیام چاپ می‌شود.
در نهایت، در تابع main دو نمونه از کلاس Car ایجاد شده است، و اطلاعات مربوط به هر نمونه به همراه پیام‌های چاپی از constructor ها نمایش داده می‌شوند.

4. inheritance یا وراثت در کاتلین چگونه است؟

یکی دیگر از سوالات مصاحبه‌ی استخدامی کاتلین در مورد inheritance یا وراثت در کاتلین است.

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

// کلاس پایه یا والد
open class Animal(val name: String) {
    fun makeSound() {
        println("Some generic sound")
    }
}

// کلاس مشتق یا زیرکلاس
class Dog(name: String, val breed: String) : Animal(name) {
    fun bark() {
        println("Woof! Woof!")
    }
}

fun main() {
    val dog = Dog("Buddy", "Labrador")
    println("Dog's name: ${dog.name}")
    println("Dog's breed: ${dog.breed}")
    dog.makeSound() // ارث بری از کلاس Animal
    dog.bark()      // تابع خاص زیرکلاس
}

در این مثال، کلاس `Animal` یک کلاس پایه است که یک ویژگی `name` را دارد و تابع `makeSound` را پیاده‌سازی کرده است. سپس کلاس `Dog` به عنوان یک کلاس مشتق از `Animal` ایجاد شده است. با استفاده از `: Animal(name)`، کلاس `Dog` از `Animal` ارث بری کرده و ویژگی `name` را به ارث می‌برد.
در تابع `main` یک نمونه از `Dog` ایجاد شده و ویژگی‌ها و توابع هر دو کلاس نمایش داده شده‌اند.
ویژگی‌ها و توابع کلاس پایه به صورت پیش‌فرض با `open` مشخص می‌شوند تا بتوانند در کلاس‌های مشتق (زیرکلاس‌ها) بازنویسی شوند. در کلاس‌های زیرکلاس نیازی به استفاده از کلمه کلیدی `open` نیست. اگر یک تابع یا ویژگی در کلاس پایه با `open` مشخص نشده باشد، در کلاس‌های مشتق از آن نمی‌توانید آن را بازنویسی کنید.

5. در مورد override توضیح دهید.

در کاتلین، `override` برای بازنویسی یک تابع یا ویژگی از کلاس پایه (کلاس والد) در یک کلاس مشتق (کلاس زیرکلاس) استفاده می‌شود. در اینجا یک آموزش کامل برای `override` در کاتلین آورده شده است:

  •  Override توابع:

برای بازنویسی یک تابع، تابع مورد نظر در کلاس زیرکلاس با استفاده از `override` تعریف می‌شود. توجه داشته باشید که تابع مورد نظر در کلاس والد نیز باید با `open` مشخص شده باشد.

open class Animal {
       open fun makeSound() {
           println("Some generic sound")
       }
   }

   class Dog : Animal() {
       override fun makeSound() {
           println("Woof! Woof!")
       }
   }
  •  Override ویژگی‌ها (Properties):

مانند توابع، ویژگی‌ها نیز با `open` در کلاس والد مشخص می‌شوند و با `override` در کلاس زیرکلاس بازنویسی می‌شوند.

open class Animal {
       open val color: String = "Unknown"
   }

   class Dog : Animal() {
       override val color: String = "Brown"
   }
  • Override توابع یا ویژگی‌های بازنویسی (Overriding Rules):

– در کلاس زیرکلاس، می‌توانید توابع یا ویژگی‌ها را بازنویسی کنید تا رفتار متفاوتی داشته باشند.
– نوع بازنویسی (override) باید با نوع اصلی (اگر هست) همخوانی داشته باشد.
– می‌توانید از کلمه کلیدی `super` برای دسترسی به تابع یا ویژگی اصلی در کلاس والد استفاده کنید.

open class Animal {
       open fun makeSound() {
           println("Some generic sound")
       }
   }

   class Dog : Animal() {
       override fun makeSound() {
           super.makeSound() // دسترسی به تابع اصلی
           println("Woof! Woof!")
       }
   }
  •  Override توابع و ویژگی‌های Abstract:

– اگر یک تابع یا ویژگی در کلاس والد با کلمه کلیدی `abstract` مشخص شده باشد، در کلاس زیرکلاس باید با `override` پیاده‌سازی شود.
– کلاسی که حداقل یک تابع یا ویژگی `abstract` دارد، خود نیز باید `abstract` باشد.

abstract class Shape {
       abstract fun draw()
   }

   class Circle : Shape() {
       override fun draw() {
           println("Drawing a circle")
       }
   }
  •  Override Interface:

یک کلاس می‌تواند از یک یا چند اینترفیس ارث بری کند. – توابع اینترفیس‌ها در کلاس مشتق باید با `override` پیاده‌سازی شوند.

interface Printable {
       fun print()
   }

   class Printer : Printable {
       override fun print() {
           println("Printing...")
       }
   }

استفاده از `override` در کاتلین از کد خوانا و قابل نگه‌داری کمک می‌کند و اطمینان حاصل می‌شود که توابع و ویژگی‌ها به درستی از کلاس والد یا اینترفیس بازنویسی شده‌اند.

اگر میخوای با سوالای بیشتری در خصوص مصاحبه استخدامی کاتلین آشنا بشی قسمت پنجم مقاله رو از دست نده…

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

 

‫5/5 ‫(1 نظر)
عاطفه امیری

View Comments

Recent Posts

بهینه‌سازی عملکرد اپلیکیشن‌های اندروید: راهنمای جامع و کاربردی

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

4 ماه ago

سوالات مصاحبه استخدام زبان کاتلین همراه با جواب(قسمت سوم)

مصاحبه استخدام زبان کاتلین یک فرصت برای ارزیابی مهارت‌ها و توانایی‌های یک برنامه‌نویس در توسعه…

4 ماه ago

سوالات مصاحبه استخدام کاتلین همراه با جواب(قسمت دوم)

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

5 ماه ago

سوالات مصاحبه استخدامی کاتلین همراه با جواب(قسمت اول)

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

5 ماه ago

نوتیفیکیشن در اندروید: نحوه کار با آن در کاتلین

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

5 ماه ago

کتابخانه Retrofit در اندروید چیست و چگونه کار میکند؟ – ترولرن

Retrofit در اندروید یک کتابخانه محبوب در جامعه توسعه‌دهندگان اندروید است که فرآیند ارسال درخواست‌ها…

5 ماه ago