brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Feb 07. 2022

Kotlin 면접 질문 #03

Kotlin interview questions

paulfranco

https://gist.github.com/paulfranco/4453383cc6df064d03087ce7aa5a0c8c




Question #01

What is a primary constructor in Kotlin?

(primary 생성자?)


Answer


primary 생성자는 클래스 헤더의 일부분이다.

Java 와 달리 클래스 body 에 정의할 필요 없다.


class Person(val firstName: String, var age: Int) {
     // class body
 }




Question #02

What is a data class in Kotlin?

(data 클래스?)


Answer


data 를 앞에 붙인, 데이터를 가지기위한 클래스


data class User(val name: String, val age: Int)


최소 1개 이상의 parameter 가 있어야 한다.

val 또는 var parameter 이어야 한다.

abstract, open, sealed, inner 는 안된다.




Question #03

Explain the Null safety in Kotlin?

(Null safety?)


Answer


Kotlin type system 은 null 참조의 위험성을 제거하는 것을 목표로 한다.

Java 를 포함한 많은 프로그래밍 언어에서 가장 일반적인 함정 중 하나는 null 참조를 하면 예외가 발생한다는 것이다.

Java 에서는 NPE(NullPointerException) 이라 한다.


Kotlin 에서는 null 을 보유할 수 있는 참조와 아닌 참조로 나눈다.


var a: String = "abc"
a = null     // compilation error


var b: String? = "abc"
b = null     // ok




Question #04

How are extensions resolved in Kotlin and what doest it mean?

(extensions?)


Answer


Extension 은 실제로 클래스를 수정하지 않습니다.

점 표기법(dot-notation) 을 이용해 새 함수를 호출할 수 있게 만듭니다.


open class BaseClass 

class DerivedClass : BaseClass() 


fun BaseClass.someMethod(){     
    print("BaseClass.someMethod") 


fun DerivedClass.someMethod(){     
    print("DerivedClass.someMethod") 


fun printMessage(base : BaseClass){     
    base.someMethod() 


printMessage(DerivedClass())        // BaseClass.someMethod


printMessage(DerivedClass()) 를 통해 출력될 메세지는 "BaseClass.someMethod" 이다.


fun printMessage(base : BaseClass){     
    base.someMethod() 
}


base.someMethod() 확장 함수는 호출되는 printMessage 함수의 base 매개변수에 선언된 타입에만 의존하기 때문입니다.

런타임에 동적으로 타입이 정해지는게 아니라 정적으로 정해집니다.




Question #05

What is a purpose of Companion Objects in Kotlin?

(Companion Objects 의 목적은?)


Answer


Kotlin 은 static members 나 member 함수가 없다.

만약 쓰고 싶다면 companion object 로 클래스 내부에 선언하면 된다.


class EventManager {     
    companion object FirebaseManager {     }   
}

val firebaseManager = EventManager.FirebaseManager


companion object 는 싱글톤입니다.

Java 코드에서 호출이 필요한 경우 @JvmStatic 을 이용할 수 있습니다.




Question #06

What is Lateinit in Kotlin and when would you use it?

(Lateinit?)


Answer


lateinit 키워드로 변수를 선언하면, 초기화를 나중에 할 수 있습니다.

초기화가 될때까지 메모리에 할당하지 않습니다.

Int, Long 과 같이 primitive 한 타입에는 쓸 수 없습니다.


lateinit var test: String

fun doSomething() {     
    test = "Some value"     
    println("Length of string is "+test.length)     
    test = "change value"
 }




Question #07

Explain lazy initialization in Kotlin

(lazy initialization?)


Answer


코드에서 해당 변수를 이용하지 않는 한, 변수는 초기화되지 않습니다. 

한 번만 초기화되고 항상 같은 값만 가지고 있습니다.


lazy() 함수는 람다를 통해 lazy 인스턴스를 반환받습니다.

첫번째 get() 호출은 lazy() 람다를 실행해 결과를 저장하고, 이후 get() 호출은 단순히 저장된 결과를 반환만 합니다.


val test: String by lazy {     
    val testString = "some value"
}




Question #08

When to use lateinit over lazy initialization in Kotlin?

(lateinit? lazy initialization? 언제 쓰나?)


Answer


속성이 mutable 일 경우 lateInit 이용

속성이 외부에서 설정된 경우(설정하기 위해 외부 변수를 전달해야 하는 경우) lateInit 이용

한 번만 초기화되고 모두가 공유하도록 되어 있고, 내부적으로 설정되어 있으면 lazy initialization 이용


lateInit

모든 위치에서 초기화할 수 있다.

다중 초기화가 가능하다.

Non-thread safe

var 만 이용 가능하다.

값 초기화 여부를 확인하기 위해 isInitialized 함수 존재 함

primitive 타입 속성 비허용


lazy initialization

initializer 람다에서만 초기화 할 수 있다.

한 번만 초기화할 수 있다.

기본적으로 스레드로부터 안전하며, 초기화가 한 번만 호출되도록 보장합니다.

val 만 이용 가능하다.

초기화를 취소할 수 없습니다.

primitive 타입 속성에 허용




Question #09

What is the difference between var and val in Kotlin?

(var, val 차이는?)


Answer


var 는 일반 변수와 같으며 mutable 변수로, 여러 번 할당할 수 있습니다.

val 는 Final 변수와 같으며 immutable 변수로, 한 번만 초기화할 수 있습니다.




Question #10

Explain what is wrong with that code?

(아래 코드에서 잘못된점은?)


class Student (var name: String) {
     init() {
         println("Student has got a name as $name")
     }

     constructor(sectionName: String, var id: Int) this(sectionName) { }
}


Answer


클래스의 property 를 secondary 생성자에 선언할 수 없습니다.


class Student (var name: String) {
     
    var id: Int = -1

     init() {
         println("Student has got a name as $name")
     }

    constructor(secname: String, id: Int) this(secname) {
         this.id = id
     }
}




Question #11

What will be result of the following code execution?

(아래 코드 실행 결과는?)


val aVar by lazy {
     println("I am computing this value")
     "Hola"
 }

fun main(args: Array<String>) {
     println(aVar)
     println(aVar)
}


Answer


I am computing this value
 Hola
Hola




Question #12

What is the difference between "open" and "public" in Kotlin?

(open 과 public 차이는?)


Answer


open 키워드는 "open for extension" 을 의미합니다.

Java 의 final 과 반대입니다.

open 키워드를 통해 해당 클래스를 상속할 수 있습니다.


visibility modifier 를 지정하지 않으면 기본적으로 public 입니다. 




Question #13

What is the difference between “const” and “val”?

(const 와 val 차이는?)


Answer


const 는 컴파일 타임 상수입니다.

런타임에 할당받는 val 와 달리, 컴파일 타임 동안 값을 할당 받습니다.


따라서 const 는 함수나 클래스 생성자에 할당할 수 없고, String 또는 primitive 타입만 할당할 수 있습니다.




Question #14

May you use IntArray and an Array is in Kotlin interchangeably?

(IntArray 와 Array 를 같이 쓸 수 있나?)


Answer


Array<Int> => Integer[]

IntArray => int[]


서로 다른 타입이기 때문에 같이 쓸 수 없다.




Question #15

How would you create a singleton with parameter in Kotlin?

(parameter 가 있는 싱글톤 작성)


Answer


object 는 생성자가 없기 때문에 parameter 전달이 불가능하다.


아래처럼 전달할 수 있다.

class UsersDatabase : RoomDatabase() {

     companion object {
         @Volatile private var INSTANCE: UsersDatabase? = null

         fun getInstance(context: Context): UsersDatabase =
             INSTANCE ?: synchronized(this) {
                 INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
             }

         private fun buildDatabase(context: Context) =             Room.databaseBuilder(context.applicationContext,                     UsersDatabase::class.java, "Sample.db")
                     .build()
     }

 }




Question #16

What is inline class in Kotlin and when do we need one?

(inline 클래스란?)


Answer


Primivite 타입에 대한 inline 을 제공한다.


단일 property 가 있는 기본 생성자를 가진 클래스 앞에 inline 수정자를 붙이면, 아래와 같이 컴파일 시 값으로 대체됩니다.

함수는 정적 함수가 됩니다.


inline class Name(private val value: String) { 
    fun greet() {
        // ...
    }
}
// Code
val name: Name = Name("Marcin")
name.greet()

// During compilation replaced with code similar to:
val name: String = "Marcin"
Name.`greet-impl`(name)


primary 생성자에서 초기화된 단일 property 는 필수입니다.

Init block, inner class, backing field 는 허용하지 않습니다.

interface 만 상속할 수 있습니다.

final 과 같은 효과입니다.




Question #17

Explain the difference between Inline classes vs type aliases

(inline 클래스와 type aliases 차이는?)


Answer


type aliases 는 동일한 타입을 가지고 있으면 호환이 되고,
inline 클래스는 호환이 안됩니다.


typealias NameTypeAlias = String
inline class NameInlineClass(val s: String)

fun acceptString(s: String) {}
fun acceptNameTypeAlias(n: NameTypeAlias) {}
fun acceptNameInlineClass(p: NameInlineClass) {}

fun main() {
     val nameAlias: NameTypeAlias = ""
     val nameInlineClass: NameInlineClass = NameInlineClass("")
     val string: String = ""

    // OK: pass alias instead of underlying type
     acceptString(nameAlias)

    // Not OK: can't pass inline class instead of underlying type     
    acceptString(nameInlineClass) 

    // OK: pass underlying type instead of alias
     acceptNameTypeAlias(string)

    // Not OK: can't pass underlying type instead of inline class
     acceptNameInlineClass(string) 

}




Question #18

What is Kotlin backing field is used for?

(backing field 는 어디에 쓰이는가?)


Answer


Backing field 는 접근자(getter/setter) 내에서만 이용할 수 있는 자동 생성된 필드입니다.


var selectedColor: Int = someDefaultValue
         get() = field
         set(value) {
             field = value
         }




Question #19

How does the reified keyword in Kotlin work?

(reified 키워드 동작 방법은?)


Answer


fun <T> myGenericFun(c: Class<T>)


myGenericFun 함수에서는 T 타입을 알 수 없습니다.

Java 에서와 같이 런타임에 지워지고 컴파일 시 이용할 수 있기 때문입니다.


inline fun <reified T : Activity> Activity.startActivity() {
     startActivity(Intent(this, T::class.java))
}


inline 함수와 함께 reified 키워드를 쓰면, T 타입을 알 수 있습니다.


이러한 함수는 컴파일러가 함수의 바이트코드를 함수가 이용되는 모든 위치에 복사합니다.

따라서 컴파일러는 reified 타입의 실제 타입을 알고 있습니다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari