Kotlin: A pragmatic language by JetBrains
-
Upload
jigar-gosar -
Category
Technology
-
view
221 -
download
0
Transcript of Kotlin: A pragmatic language by JetBrains
Kotlin
A pragmatic language for JVM and Android
What if I told you that
you already know Kotlin
But who am I?
@jigargosar
I am anAgile Coach
And Code Doctor
Conventions used in this talk
● Never == Almost Never● Always == Almost always● same goes for right, wrong, good, bad, 100%, 0%
What if I told you that
you already know Kotlin
Hello Kotlin
fun main(args: Array<String>) { println("Hello Kotlin!")}
What is Kotlin?a pragmatic programming
language for JVM and Android
Combines OO and functional features
Focused on
● interoperability● safety ● clarity ● tooling support
Kotlin works everywhere where Java works
Kotlin works everywhere where Java works
● Server-side applications● Mobile applications (Android)● Desktop applications● Works with all major tools and services such as
○ IntelliJ IDEA, Android Studio and Eclipse○ Maven, Gradle and Ant○ Spring Boot○ GitHub, Slack and even Minecraft
Key focus is on interoperability and seamless support for mixed Java+Kotlin projects
Is it mature enough and ready for
production?
Is it ready for production?
● Yes. And for quite some time.
● JetBrains, have been using Kotlin in real-life projects on
a rather extensive scale over the last two years.
● Over 500K lines of Kotlin code in projects such as IntelliJ IDEA and Rider.
● In addition, there are quite a few companies that have been using Kotlin in production for some time now.
Who’s behind Kotlin?
First and foremost, Kotlin is an Open Source language
Open Source language
● Developed on GitHub ● Under Apache 2.0 Open-Source license
● Over 100 contributors to date
● Adoption: 2 million+ Kotlin LOC on GitHub
BUT JetBrains is the main backer of Kotlin
Why Kotlin?
Concise, Safe, Versatile, Interoperable, Tooling
ConciseDrastically reduce the amount of boilerplate code you need to write.
Concise
Create a POJO with getters, setters, equals(), hashCode(), toString() and copy() in a single line:
data class Customer(val name: String, val email: String, val company: String)
Concise
Or filter a list using a lambda expression:
val positiveNumbers = list.filter {it > 0}
Concise
Want a Singleton? Create an object:
object ThisIsASingleton {
val companyName: String = "JetBrains"
}
SafeAvoid entire classes of errors such as null pointer exceptions.
SAFE
Get rid of those pesky NullPointerExceptions, you know, The Billion Dollar Mistake
var output : Stringoutput = null // compilation error
And of course, Kotlin protects you from mistakenly operating on nullable types, including those from Java
println(output.length()) // compilation error
SAFE
And if you check a type is right, the compiler will auto-cast it for you
fun calculateTotal(obj: Any) { if (obj is Invoice) { obj.calculateTotal() }}
VersatileBuild server-side applications, Android apps or frontend code running in the browser.
Versatile
Multi-purpose language allowing you to build any type of application
● Android Development: No performance impact. Very small runtime.● JavaScript: Write code in Kotlin and target JavaScript to run on Node.js or in
browser● Web: Whether you want strongly typed HTML, CSS builders or just plain web
development.● Application Server
○ The technology doesn't matter. 100% compatible with all JVM frameworks.
● Enterprise: Use Kotlin for any type of Enterprise Java EE development.
InteroperableLeverage existing frameworks and libraries of the JVM with 100% Java Interoperability.
Create and consume Java code at will
class NettyHandler: ChannelInboundMessageHandlerAdapter<Any>() {
override fun messageReceived(p0: ChannelHandlerContext?, p1: Any?) { throw UnsupportedOperationException() }}
Or use any existing library on the JVM, as there’s 100% compatibility, including SAM support.
Interoperable
Interoperable
Target either the JVM or JavaScript. Write code in Kotlin and decide where you want to deploy to
import js.dom.html.*
fun onLoad() { window.document.body.innerHTML += "<br/>Hello, Kotlin!"}
ToolingCommand Line Compiler or First Class IDE Support. Freedom to choose.
Basics
Let’s look at real code
Functions
fun sum(a: Int, b: Int): Int {
return a + b
}
fun sum(a: Int, b: Int) = a + b
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
Variables
val a: Int = 1
val b = 1 // `Int` type is inferred
val c: Int // Type required when no initializer
// is provided
c = 1 // definite assignment
var x = 5 // `Int` type is inferred
x += 1
String Interpolation & docstring
val i = 10
val s = "i = $i" // evaluates to "i = 10"
val s = "abc"
val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
val price = """
${'$'}9.99
"""
Conditional Expression
fun max(a: Int, b: Int): Int {
if (a > b)
return a
else
return b
}
fun max(a: Int, b: Int) = if (a > b) a else b
When Expressionwhen (x) {
1 -> print("x == 1")
2 -> print("x == 2")
0, 1 -> print("x == 0 or x == 1")
parseInt(s) -> print("s encodes x")
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
is String -> x.startsWith("prefix")
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("otherwise")
}
For Loop, while & do..while
for (item in collection)
print(item)
for (i in array.indices)
print(array[i])
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
Collections
val immutableList = listOf(1, 2, 3)
val mutable = arrayListOf(1, 2, 3)
val immutableMap = mapOf("foo" to 1, "bar" to 2)
val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
println(map["foo"])
Advanced
Let’s look at real code
null safety
Kotlin’s type system is aimed to eliminate NullPointerException’s from our code. The only possible causes of NPE’s may be:
● An explicit call to throw NullPointerException()● External Java code has caused it● There’s some data inconsistency with regard to initialization (an uninitialized
this available in a constructor is used somewhere)
null safety
var a: String = "abc"
a = null // compilation error
val l = a.length // safe
var b: String? = "abc"
b = null // ok
val l = if (b != null) b.length else -1
val l = b.length // error: variable 'b' can be null
null safety - Smart Cast
if (b != null && b.length > 0)
print("String of length ${b.length}")
else
print("Empty string")
Smart Type Checks and Casts
if (obj is String) {
print(obj.length) // obj is automatically cast to String
}
if (obj !is String) { // same as !(obj is String)
print("Not a String")
}
else {
print(obj.length)
}
Smart Type Checks and Casts
if (x !is String) return
print(x.length) // x is automatically cast to String
“Unsafe” cast operator
val x: String = y as String // y can’t be null else CCE
val x: String? = y as String? // y can’t be Int
val x: String? = y as? String // y can be anything
Extensions
Extension Functions
fun String.last(): Char { return this[lastIndex]}fun String.last() = this[lastIndex]
val lastChar = "abc".last();println("lastChar = ${lastChar}")
Nullable Receiver
fun Any?.toString(): String {
if (this == null) return "null"
return toString() // why does this compile?
}
More about Extension
● Extensions are resolved statically● Extension Properties● Companion Object Extensions● Scope of Extensions● Declaring Extensions as Members
https://kotlinlang.org/docs/reference/extensions.html
Motivation behind
Extensions?
Classes and Inheritance
Classes and Inheritanceclass Empty
class Person(firstName: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}
class Person(val firstName: String, val lastName: String, var age: Int) {
// ...
}
Classes and Inheritance
open class A {
open fun f() { print("A") }
fun a() { print("a") }
}
interface B {
// interface members are 'open' by
default
fun f() { print("B") }
fun b() { print("b") }
}
class C() : A(), B {
// The compiler requires f() to be
overridden:
override fun f() {
super<A>.f() // call to A.f()
super<B>.f() // call to B.f()
}
}
More about Classes and Inheritance
https://kotlinlang.org/docs/reference/classes.html
Data Classes
Data Classes
data class User(val name: String, val age: Int)
data class User(val name: String = "", val age: Int = 0)
● equals()/hashCode() pair,
● toString() of the form "User(name=John, age=42)",
● componentN() functions corresponding to the properties in their order of declaration,
● copy() function (see below).
Data Classes: Copying
// generated by compiler for previous class
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
Data Classes and Destructuring Declarations
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age")
// prints "Jane, 35 years of age"
Generics
Generics
class Box<T>(t: T) {
var value = t
}
val box: Box<Int> = Box<Int>(1)
val box = Box(1)
// 1 has type Int,
// so the compiler figures out that we are talking about Box<Int>
Generics
https://kotlinlang.org/docs/reference/generics.html
Extra
Functions Infix Notation
val a = 1 to 3
val b = "a".to("z")
val c: Pair<String, String> = "a" to "z"
Packagespackage foo.bar
fun baz() {}
class Goo {}
------------------------------------------
import foo.Bar // Bar is now accessible without qualification
import bar.Bar as bBar // bBar stands for 'bar.Bar'
import foo.* // everything in 'foo' becomes accessible