Recent Guides

In the last article, we discovered how Kotlin’s new, experimental inline classes feature allows us to “create the data types that we want without giving up the performance that we need.” We learned that:
Inline classes wrap an underlying value. When the code is compiled, instances of the inline class get replaced with the underlying value. This can improve our app’s performance, especially when the underlying type is a primitive.

Whether you’re writing massive data-chomping processes that execute in the cloud, or apps running on low-powered cell phones, most developers want their code to run fast. And now, Kotlin’s new, experimental inline classes feature allows us to create the data types that we want without giving up the performance that we need!
In this new series of articles, we’re going to take a look at inline classes from top to bottom!

Are you ready to start exploring inline classes? Since they’re still an experimental feature, you’ll need to take a few extra steps to enable them in your project. It’s not difficult to set up, but there are a few things to watch out for. This guide will help you navigate those issues so that you can start playing with Kotlin 1.3 and inline classes today.
For these instructions, I’m assuming you’re using IntelliJ IDEA or Android Studio.

If you’ve ever had trouble remembering the difference between parameters and arguments, today’s article is for you! Understanding this distinction can help when we’re talking about functions, and it can help even more when we’re talking about generics.
Parameters and Arguments - the TL;DR It’s a parameter when you’re inside the definition. It’s an argument when you’re outside the definition. The easiest way to recall the difference between the two is to associate the word argument with the word outside, by remembering this phrase:

Have you ever had a conversation like this?
Hopefully you haven’t had a conversation like that in real life, but you might have had one like that with your code!
For example, take a gander at this:
interface RestaurantPatron { fun makeReservation(restaurant: Organization<(Currency, Coupon?) -> Sustenance>) fun visit(restaurant: Organization<(Currency, Coupon?) -> Sustenance>) fun complainAbout(restaurant: Organization<(Currency, Coupon?) -> Sustenance>) } When you see a chunk of code with so many types smushed together, it’s easy to get lost in the details.

Have you ever wondered how star-projections work? Or why they change your function parameter and return types? Or why it seems like sometimes you can actually get by without them?
In the first article in this series, An Illustrated Guide to Covariance and Contravariance in Kotlin, we uncovered two simple, easy-to-understand rules that illuminate variance, and saw how they applied to regular class and interface inheritance in Kotlin.
In the second article, The Ins and Outs of Generic Variance in Kotlin, we saw how those same two rules played out for generics, discovering what type projections are and how they work.

Have you ever wondered why generic variance works like it does? Or why Kotlin won’t let you use a type parameter as an argument when it’s marked as out? Have you wondered why the compiler sometimes won’t let you call a certain function on a generic?
Yes, generics can seem mysterious, but with just two simple, easy-to-understand rules, we can reason our way through almost everything related to variance.

Generics can often seem confusing. How often have you started to solve a problem with generics, only to realize that they don’t quite work like you thought they did?
The good news is that there are some simple, foundational concepts that underpin generic variance. And once you understand those concepts, you won’t have to memorize acronyms or resort to trial-and-error - you’ll simply understand how and why they work!

Let’s think for a moment about everything that you can do with a class name in Kotlin - think of all the cases where you literally type out the name of a class in your source code. I came up with the following 15 cases, but I probably missed a few. Get your scrolling finger ready, here we go…
1. Define a member property:
private val thing: Thing 2.

Kotlin allows you to constrain a type parameter on a generic when you declare it, limiting the range of types that it can accept. Why is this helpful? Well, let’s take a look at an example.
Let’s say you’ve got a few pets at home, and you want to pick a favorite:
fun <T> chooseFavorite(pets: List<T>): T { val favorite = pets[random.nextInt(pets.size)] // This next line won't compile - because `name` can't be resolved println("My favorite pet is ${favorite.