• +91 9723535972
  • info@interviewmaterial.com

Kotlin Interview Questions and Answers

Kotlin Interview Questions and Answers

Question - 91 : - How to implement Builder pattern in Kotlin?

Answer - 91 : -

First and foremost, in most cases you don't need to use builders in Kotlin because we have default and named arguments but if you need one use:

class Car( //add private constructor if necessary
        val model: String?,
        val year: Int
) {

    private constructor(builder: Builder) : this(builder.model, builder.year)

    class Builder {
        var model: String? = null
            private set

        var year: Int = 0
            private set

        fun model(model: String) = apply { this.model = model }

        fun year(year: Int) = apply { this.year = year }

        fun build() = Car(this)
    }
}
Usage:

val car = Car.Builder().model("X").build()

Question - 92 : - How does the reified keyword in Kotlin work?

Answer - 92 : -

In an ordinary generic function like myGenericFun, you can't access the type T because it is, like in Java, erased at runtime and thus only available at compile time. Therefore, if you want to use the generic type as a normal Class in the function body you need to explicitly pass the class as a parameter like the parameter c in the example.

fun myGenericFun(c: Class)
By marking a type as reified, we’ll have the ability to use that type within the function.

As for a real example, in Java, when we call startActivity, we need to specify the destination class as a parameter. The Kotlin way is:

inline fun Activity.startActivity() {
    startActivity(Intent(this, T::class.java))
}
You can only use reified in combination with an inline function. Such a function makes the compiler copy the function's bytecode to every place where the function is being used (the function is being "inlined"). When you call an inline function with reified type, the compiler knows the actual type used as a type argument and modifies the generated bytecode to use the corresponding class directly. Therefore calls like myVar is T become myVar is String (if the type argument were String) in the bytecode and at runtime.

Question - 93 : - What is a motivation to make classes final by default in Kotlin? Do you agree with that decision?

Answer - 93 : -

  • First Kotlin takes many ideas from the functional programming world and uses immutability as often as it can to avoid all the known problems with mutation. Also proper designing a class for inheritance requires an excruciating amount of work (and building at least 3 separate subclasses, to verify that you base class actually is useful). Most classes should be final. Extending them is probably a bad idea.

  • The second thought which comes to my mind is that inheritance is often missused. There is the principle "Favor composition over inheritance" as a guideline for better designs. So declaring every class as final by default forces the developer to at least stop for a moment and think about alternative ways to solve the problem instead of using inheritance for the wrong reasons.

Question - 94 : - What is The Billion Dollar Mistake?

Answer - 94 : -

Kotlin's type system is aimed at eliminating the danger of null references from code, also known as the The Billion Dollar Mistake.

One of the most common pitfalls in many programming languages, including Java, is that accessing a member of a null reference will result in a null reference exception. In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references).

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object-oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

Question - 95 : - Why would you use apply in Kotlin?

Answer - 95 : -

Look at this code:

person.name = "Tony Stark"
person.age = 52
and equivalent with apply will be:

val person = Person().apply {
    name = "Tony Stark" // this. can be omitted
    age = 52 // this. can be omitted
    // ...
}
This way you don't have to repeat person several times. Apply is used to keep things that belong together in one place (mostly initializations).

Question - 96 : - Provide a real use case when inline classes may be useful

Answer - 96 : -

Imagine an authentication method in an API that looks as follows:

fun auth(userName: String, password: String) { println("authenticating $userName.") }
Since both parameters are of type String, you may mess up their order which gets even more likely with an increasing number of arguments.

Inline class wrappers around these types can help you mitigate that risk and give you simple, type-safe wrappers without introducing additional heap allocations:

inline class Password(val value: String)
inline class UserName(val value: String)

fun auth(userName: UserName, password: Password) { println("authenticating $userName.")}

fun main() {
    auth(UserName("user1"), Password("12345"))
    //does not compile due to type mismatch
    auth(Password("12345"), UserName("user1"))
}

Question - 97 : - Explain the difference between lateinit and lazy in details

Answer - 97 : -

Here are the significant differences between lateinit var and by lazy { ... } delegated property:

  • lazy { ... } delegate can only be used for val properties, whereas lateinit can only be applied to vars, because it can't be compiled to a final field, thus no immutability can be guaranteed;

  • lateinit var has a backing field which stores the value, and by lazy { ... } creates a delegate object in which the value is stored once calculated, stores the reference to the delegate instance in the class object and generates the getter for the property that works with the delegate instance. So if you need the backing field present in the class, use lateinit;

  • In addition to vals, lateinit cannot be used for nullable properties and Java primitive types (this is because of null used for uninitialized value);

  • lateinit var can be initialized from anywhere the object is seen from, e.g. from inside a framework code, and multiple initialization scenarios are possible for different objects of a single class. by lazy { ... }, in turn, defines the only initializer for the property, which can be altered only by overriding the property in a subclass. If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit.

  • Initialization by lazy { ... } is thread-safe by default and guarantees that the initializer is invoked at most once (but this can be altered by using [another lazy overload][1]). In the case of lateinit var, it's up to the user's code to initialize the property correctly in multi-threaded environments.

  • A Lazy instance can be saved, passed around and even used for multiple properties. On contrary, lateinit vars do not store any additional runtime state (only null in the field for uninitialized value).

  • If you hold a reference to an instance of Lazy, [isInitialized()][2] allows you to check whether it has already been initialized (and you can [obtain such instance with reflection][3] from a delegated property). To check whether a lateinit property has been initialized, you can [use property::isInitialized since Kotlin 1.2][4].

  • A lambda passed to by lazy { ... } may capture references from the context where it is used into its [closure][5].. It will then store the references and release them only once the property has been initialized. This may lead to object hierarchies, such as Android activities, not being released for too long (or ever, if the property remains accessible and is never accessed), so you should be careful about what you use inside the initializer lambda.


NCERT Solutions

 

Share your email for latest updates

Name:
Email:

Our partners