By Mike Cleron, Director,
Android Platform
Today the Android team is excited to announce that we are officially adding
support for the Kotlin programming
language. Kotlin is a brilliantly designed, mature language that we believe will
make Android development faster and more fun. It has already been adopted by
several major developers � Expedia, Flipboard, Pinterest, Square, and others �
for their production apps. Kotlin also plays well with the Java programming
language; the effortless interoperation between the two languages has been a
large part of Kotlin's appeal.
The Kotlin plug-in is now bundled with Android Studio 3.0 and is available for
immediate download.
Kotlin was developed by JetBrains, the
same people who created IntelliJ,
so it is not surprising that the IDE support for Kotlin is outstanding.
In addition to the IDE support, we're announcing a collaboration with JetBrains
to move Kotlin into a non-profit foundation. (Kotlin is already open sourced
under Apache2.)
- Download
Android Studio 3.0 - Open one of your existing ".java" files
- Invoke "Code > Convert Java File to Kotlin File"
Say "Hello" to Kotlin
Kotlin will be very familiar to anyone who has used the Java programming
language.
package helloWorld
fun main(args: Array) {
println("Hello World!")
}
At first glance, you will see comforting elements like curly braces, classes,
packages, functions and methods. But as you go deeper, you will discover that
although Kotlin is based on familiar concepts, it is a uniquely modern, elegant
and pragmatic riff on those models. In particular, Kotlin is highly expressive
with minimal syntactic friction between your thoughts and what you have to type
in order to express those thoughts. If when writing code you have asked yourself
questions that began "why do I have to �?" you will be pleased to learn that in
Kotlin the answer to many of those questions is "you don't!"
For example, perhaps you have asked why you need to type in a bunch of
boilerplate getters and setters as well as overriding
equals()
,hashCode()
and toString()
when implementing a simpleclass. Here is a typical example from the Java programming language (in a
microscopic font for brevity).
public class Customer {
private String name;
private String email;
private String company;
public Customer(String name) {
this(name, "", "");
}
public Customer(String name, String email) {
this(name, email, "");
}
public Customer(String name, String email, String company) {
this.name = name;
this.email = email;
this.company = company;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Customer customer = (Customer) o;
if (name != null ? !name.equals(customer.name) : customer.name != null) return false;
if (email != null ? !email.equals(customer.email) : customer.email != null) return false;
return company != null ? company.equals(customer.company) : customer.company == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (email != null ? email.hashCode() : 0);
result = 31 * result + (company != null ? company.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
", company='" + company + '\'' +
'}';
}
}
In Kotlin, you don't have to type any of that. This single line is equivalent to
the entire class above.
data class Customer(var name: String, var email: String = "",
var company: String = "")
History and Reference
Kotlin has been around for quite a while; it was announced back in 2011 and the
first preview was released in 2012. Kotlin 1.0 was released in 2016, at which
point JetBrains committed to maintaining backwards compatibility for stable
features from 1.0 forward.
You can find excellent training material and references at https://kotlinlang.org/. The Android team has
found the Kotlin
Koans tutorial to be especially helpful as a quick way to get started
writing some Kotlin snippets. These tutorials range from the simple to the
sublime as the material progresses from the basics to more sophisticated Kotlin
idioms.
Why Kotlin?
Why did the Android team decide to support Kotlin? Most importantly, it was
because we think Kotlin is a great language that will make writing Android apps
easier and more enjoyable.
Kotlin is also a great match for the existing Android ecosystem. It is 100%
compatible with the Java programming language. You can add as little or as much
Kotlin into your existing codebase as you want and mix the two languages freely
within the same project. Calling out to Kotlin code from code written in the
Java programming language Just Works�. Going the other direction usually works
without any developer effort too via some automatically applied translation
conventions (for example, things like property getters and setters are created
for you). With the help of a few Kotlin annotations, you can also customize how
the translation is performed.
Finally, many, many developers have told us they love the Kotlin language. (Many
of our own developers on the Android team have also been saying similar things.)
There is already an enthusiastic
community
of Kotlin developers
for Android, and the Android team has been routinely peppered with questions
about Kotlin at public events. The Android community has spoken, and we
listened.
A Quick Tour
To help you get a sense of where all of the excitement around Kotlin is coming
from, here is a quick, very-much-not-comprehensive tour of some of the
particularly appealing aspects of Kotlin:
Nullable
The Kotlin compiler enforces that variables that can hold null values are
explicitly declared � thus no more NullPointerExceptions at runtime!
var neverNull: String = "something"
var mightBeNull: String? = null // "?" indicates this can be null
if (neverNull.length > 0) { // This is OK
�
}
if (mightBeNull.length > 0) { // Compiler catches this error for you
�
}
Named parameters and default arguments
We've all seen methods that have too many parameters to keep track of. For
example:
fun orderPizza(size: Size, pepperoni: Boolean, mushrooms: Boolean,
ham: Boolean, pineapple: Boolean, pickles: Boolean,
sausage: Boolean, peppers: Boolean, onion: Boolean)
{
...
}
// Wait� did I just order pickles on my pizza?
// Why do we even have that option?
orderPizza(Size.LARGE, true, false, false, false, true,
false, true, false)
Compare that to a similar scenario using named parameters and default arguments:
fun orderPizza(size: Size,
pepperoni: Boolean = false,
mushrooms: Boolean = false,
ham: Boolean = false,
pineapple: Boolean = false,
pickles: Boolean = false,
sausage: Boolean = false,
peppers: Boolean = false,
onion: Boolean = false)
{
...
}
orderPizza(Size.LARGE, ham = true, mushrooms = true)
In addition to helping to avoid tragic pizza outcomes, this is much easier to
read. It also reduces the number of variants of overloaded functions you need to
write.
When statement
Kotlin has a variation of a switch statement that allows matching on arbitrary
expressions.
// Please don't put this in your app!
when {
password.equals("password") -> println("Insecure password!")
password.length < 4 -> println("Too short!")
else -> {
println("Secure password!")
}
}
Smart Casts
Why should you have to cast something to a class right after you just tested
that it is an instance of that class? In Kotlin, you don't have to do that
anymore.
if (obj is String) {
// Compiler casts obj to a String for you.
// (Would work with && instead of nested ifs too.)
if (obj.length > 0) {
�
}
}
This generalizes to the when statement as well:
// Assume reasonable implementations of Cat and Dog
when (obj) {
is Cat -> obj.meow(...)
is Dog -> obj.woof(...)
else -> {
�
}
}
Extension functions
Kotlin lets you essentially retcon
new methods onto an existing type. If you, like many people, wish that the
String class had a
toPigLatin
method, you can now add it yourselfwithout having to create a new helper class to wrap String or going through the
trouble of serving on a language committee:
// The "String." prefix indicates that this method should
// extend the existing String class
fun String.toPigLatin() : String {
...
}
val plainOldString : String = "some text"
// Can now call toPigLatin as if were a method on String
println(plainOldString.toPigLatin())
// Or:
println("some text".toPigLatin())
Destructuring Declarations
We have already seen how easy it is to define a simple data class:
data class Order(val itemCode: String, val quantity: Int,
val price: Float)
A function that uses one of these classes as the return type is very close to
supporting multiple return values:
fun getOrder(...): Order {
...
return Order(itemCode, quantity, price);
}
To get all the way there, you can use the destructuring declaration syntax. The
following statement takes the
Order
object, extracts its threeproperties, and then assigns them to the three variables
what
,howMany
and howMuch
� all courtesy of the Kotlincompiler, which also infers the correct types for you.
val (what, howMany, howMuch) = getOrder(...)
Lambdas
Kotin has an extremely concise syntax for lambdas that makes is easy to express
powerful functional programming paradigms. Here's a simple example that uses a
lambda to test that everything in a collection is a String:
fun allStrings(collection: Collection)=
collection.all { it is String }
That lambda syntax is building block of one of Kotlin's coolest features: the
ability to create builders that use JSON-like syntax that also happens to be
syntactically valid Kotlin. This example is adapted from an extended discussion
here,
but you can get the flavor of what it possible with this snippet:
fun generatePage(withEmphasis : Boolean) {
val result =
html {
head {
title { +"Kotlin Builders" }
}
body {
h1 { +"Kotlin Builders" }
p {
+"This is "
if (withEmphasis) b { +"really " }
+"interesting"
a(href = "https://goo.gl/rHwJio") { +"More here" }
}
}
}
println(result)
}
There are a couple of interesting things going on here. First, this shows how
expressive Kotlin's functional syntax can be: in this example,
"
html
", "head
", "body
, etc. are all justfunctions written in Kotlin and the stuff in curly braces that follows are
functional parameters. (This snippet uses functions with names that match HTML
tags to build a representation of a web page, but of course you can use this
pattern to build any complex data structure with whatever names you want.) The
second interesting thing is the "
withEmphasis
" conditional. Thismay look like we are mixing code (
if (withEmphasis)
�) with data(all the HTML-esque tags), but the "data" here is actually just more code. Since
it is all really just code, this lets you build complex data structures using a
declarative syntax while also having inline access to the full capabilities of
the Kotlin language.
Getting Started
If you want to get started with Kotlin, you can start playing with code online
immediately here. Just hit the green
triangle to compile and run.
To try Kotlin in your app, follow these steps:
The IDE will then walk you through adding Kotlin dependencies into your project,
and then convert the code to functionally equivalent Kotlin code. (The IDE will
also offer to touch up all of the call sites to the converted class when
suitable to be more idiomatic Kotlin such as when static methods are moved to
companion objects.)
You can also find a lot more information on how to start using
Kotlin on developer.android.com.
No comments:
Post a Comment