4. About Me
Ing. Marco Vasapollo
C. E. O. & Founder @ MetaRing
C. E. O. & Founder @ Aequalitam Foundation
Mail: ceo@metaring.com
Skype: marco.vasapollo
https://www.metaring.com
https://www.aequalitam.org
6. Warnings
•Kotlin is NOT Java
•It has its own APIs (for cross-platform reasons)
•Kotlin understands Java because of Plugins
•Plugins convert Kotlin APIs into Java APIs*
*when needed
7. How it works
HelloWorld.class
kotlin-compiler
HelloWorld.kt
import java.util.List;
import java.util.Date;
import ……
Access to all Java
libraries
org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
• Via command line
• Via official/unofficial IDE plugins (Eclipse, IntelliJ Idea,Visual
Studio Code)
• Via Packages Managers (Maven, Gradle)
Plain Classic Java ByteCode (No Java source needed)
9. HelloWorld.kt
fun main(args : Array<String>) {
println(“Hello, world!”)
}
class Greeter(val name : String) {
fun greet() {
println("Hello, $name");
}
}
fun main(args : Array<String>) {
Greeter(args[0]).greet()
}
The simple way The OO Way
VS
10. Variables
var name : String = “Marco”
var name = “Marco”; //; can be omitted
val name = “Marco” //readonly, like Java final
val name : String
//0, 1, or more instructions later…
name = “Marco”
name = “Giuseppe” //cannot do this, once it’s assigned, value cannot be changed
var name : String? = null; //vars and vals are NullSafe by default, to allow
null you have to insert ‘?’ at the end
11. If
var a = 11
var b : String
if(a > 10) {
b = “foo”
} else {
b = “bar”
}
var a = 11
var b = if(a > 10) {
“foo”
} else {
“bar”
}
var a = 11
var b = if(a > 10) “foo” else “bar”
In Kotlin, if is an expression, not just a simple construct
Ternary operator does NOT exists, so you cannot do:
var b = a > 10 ? “foo” : “bar”
12. When
var a = 11
var b = when {
a > 10 -> “foo”
a < 10 -> “bar”
else -> “default case”
}
No need of switch construct. when operator is extremely powerful
var a = 11
var b = when(a) {
10 -> “foo”
11 -> “bar”
else -> “default case”
}
var a = 11
when {
a > 10 -> println(“foo”)
a < 10 -> println(“bar”)
else -> println(“default case”)
}
13. Nullables
var a : String? = “foo” //Can be null
var b = a.length //Syntax ERROR: a can be null and b is IMPLICITLY NullSafe
var b = if (a != null) a.length else -1 //Correct form
var b = a?.length //Same as above. But this time b is implicitly Int?
var name = bob?.department?.head?.name //Safe calls can be Concatenated
a?.let {println(a.length)} //If a is not null, execute this lambda expression
var b = a?.length ?: -1 //Elvis operator, if value to the left of ?: is null,
then use the one to the right. In this case b is Int
var b = a!!.length //a.length or NullPointerException
14. Equality
var eq = a === b //referential equality
var eq = a.equals(b) //Structural equality
var eq = a == b //syntactic sugar for a?.equals(b) ?: (b === null)
15. Strings
var name = “Marco”
var message = “My name is ” + name + “, pleasure to meet you”
message = “My name is ${name}, pleasure to meet you”//$name is correct too
var user = //get user data object from somewhere...
message = “My name is ”${user.name}${‘”’} and my bank account has ${user.cash}${‘$’}”
//Prints: My name is “Marco” and my bank account has 500$
message = “My name is ${user.name}, my bank account has ${user.cash + 300} ${‘$’}”
message = “My bank account has ${user.cash + getOtherSavings(user.id)} ${‘$’}”
17. Arrays
var array1 = arrayOf("a", "b", "c", “d”) //Array<String> -> String[]
var array2 = arrayOf("a", "b", "c", 5) //Object[]
var array3 = arrayOfNulls<String>(10) //Array<String?>
var array4 = Array<String>(5) { "it = $it" } //for each element, execute this lambda
var list = array1.toList() //READONLY, NOT java.util.List
var mutableList = array1.toMutableList() //or list.toMutableList()
for(i in array1.indices) {//available on lists too
println(i) //prints 0,1,2,3
println(array1[i]) //prints a,b,c,d
}
for(i in array1) {
println(i) //prints a,b,c,d
}
18. Ranges
for(i in 1..4) print(i) //Prints “1234”
for(i in 1 until 4) print(i) //Prints “123”
for(i in 4 downTo 1) print(i) //Prints "4321"
for(i in 1..4 step 2) print(i) //Prints "13"
for(i in 4 downTo 1 step 2) print(i) //Prints "42“
var array1 = arrayOf("a", "b", "c", “d”)
var result = “c” in array1 //corresponds to array1.contains(“c”)
when("c") {
in array2 -> println(“foo”)
else -> println(“bar”)
}
19. Functions
fun sayMyName(name : String) { //default modifier is public, also for classes
println(“Your name is $name”)
}
fun foo() = println(“Hello!”) //Inline
fun bar() : Unit = println(“Ciao!”) //Unit is similar to Java void, can be omitted
fun main(args : Array<String>) {
var fooResult = foo() //returns Unit. Unlike Java void, it can be stored in a var
var barResult = bar() //returns Unit
//Unit is a Singleton, there is only a unique instance in all the System, so:
println(fooResult === barResult) //true
println(fooResult == barResult) //true
println(fooResult.equals(barResult)) //true
}
20. Functions
fun sum1(x : Int, y : Int) : Int {
return x + y
}
fun sum2(x : Int, y : Int) : Int = x + y //Inline, Groovy Style
var sum3 = fun(x : Int, y : Int) : Int = x + y //Anonymous function
var sum4 : (Int, Int) -> Int = { x, y -> x + y} //Type is same as sum3
fun logOperation(x : Int, y : Int, operation : (Int, Int) -> Int) {
println("Operation result between $x and $y is ${operation(x,y)}")
}
fun main(args : Array<String>) {
logOperation(3, 5, ::sum1) //references a function
logOperation(1, 4, sum3) //references an anonymous function
}
21. Packages
/* File src/Math.kt
* (match between path and package
* declaration is not mandatory) */
package marco.math
fun fantasticAbs() …
fun amazingPow() …
fun luxurySqrt() …
//File MyCode.kt
import marco.math.*
fun foo(args : Array<String>) {
fantasticAbs(...)
amazingPow(...)
luxurySqrt(...)
}
//File MyOtherCode.kt
import marco.math.amazingPow
import marco.math.luxurySqrt as thatCuteFunction
fun bar(args : Array<String>) {
amazingPow(...)
thatCuteFunction(...)
}
22. Classes
class User class User {} class User() class User() {} //All empty classes
class User(n : String) { //primary Constructor
var name = n
}
class User constructor(n : String) { //keyword constructor is omittable
var name = n
}
class User private constructor(n : String) { //needed when use modifiers or annotations
var name = n
}
class User(var name : String) //name is now a field of the User class
23. Classes
import java.util.Date
class User(var name : String) {
var minAge = 18
println(“User $name created”) //ERROR, primary constructor can only assign vars
init {
println(“User $name created”) //Use init block to add behavior to primary constructor
}
val creationTime = Date() //To instantiate an object, new keyword isn’t needed
init { //There can be more, non consecutive init blocks, they are executed sequentially
println(“Creation time: $creationTime”)
//Note that creationTime cannot be used in the first init block
}
}
24. Classes
class User(var name : String) {
constructor(age : Int) : this(“Marco”) { //Secondary constructor
// : this(...) is mandatory if primary constructor is explicitly declared
//primary constructor and init blocks are executed always and before secondary
//secondary constructors inputs like age cannot be used as class fields
//... Behavior of the secondary constructor ...
userAge = age
}
var userAge : Int
}
25. Inheritance
abstract class GeometricFigure {
abstract fun getArea() : Double
}
open class Rectangle : GeometricFigure { //classes are final by default
val x : Double
val y : Double
constructor(x : Double, y : Double) {
this.x = x
this.y = y
}
override final fun getArea() : Double = x * y
}
class Square(side : Double) : Rectangle(side, side) //super light!
26. Properties
class Rectangle(var x : Double, var y : Double) {
val area
get() = x * y //getter only, look at val
}
Class fields are Properties by default (Finally!!!!! ç_ç )
class User {
var fiscalCode : String
get
private set //getter is accessible, setter is not
//Properties value is mandatory. Use a default value, constructor input or lateinit
constructor(fiscalCode : String) = this.fiscalCode = fiscalcode
lateinit var name : String //Mandatory init before read!
var surname : String? = null
}
27. Data Classes
class User( //Common pattern: use default values in primary construction
var name : String = “”,
var surname : String = “”,
var fiscalCode : String = “”)
data class User(var name : String = “”, var surname : String = “”)
//data keyword auto generates a specific behavior for toString and equals, based on
//properties. E.G. toString -> “User(name=Marco, surname=)”
//plus, a useful copy method that can be used to clone instances in another ref
//To init (both non-data and data)
var user = User (
surname = “Rossi”, //order is not important
name = “Mario”)
var copy = user.copy(surname=“Bianchi”) //data only
28. Operators
class Point(var x = 0, var y = 0) {
operator fun inc() : Point {x++; y++; return this} //point++ on a Point var
operator fun dec() : Point {x--; y--; return this} //point–- on a Point var
operator fun plusAssign(n : Int) {x+=n; y+=n} //point += 5
}
fun main(args : Array<String>) {
var point = Point()
println(point) //Point(x=0, y=0)
point++
println(point) //Point(x=1, y=1)
point+=10 //x = 11, y = 11
}
https://kotlinlang.org/docs/reference/operator-overloading.html
29. Any
package kotlin
public open class Any {
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
val <T : Any> T.javaClass: Class<T>
}
Any is the Kotlin superclass
30. Delegates
import kotlin.reflect.KProperty
class Foo {
var bar by LoggablePropertyDelegate<String>()
}
class LoggablePropertyDelegate <T> (var value : T? = null) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
var oldValue = this.value
this.value = value
println("${property.name} in $thisRef has been changed from $oldValue to $value")
}
}
31. Delegates
interface Base {
fun printInfo()
}
class BaseImpl(val x : Int) : Base {
override fun printInfo() = print(x)
}
class Derived(b : Base) : Base by b
fun main(args: Array<String>) {
val b = BaseImpl(10)
b.printInfo() //prints 10
Derived(b).printInfo() //prints 10
}
https://kotlinlang.org/docs/reference/delegation.html
https://kotlinlang.org/docs/reference/delegated-properties.html
32. Extension Methods
abstract class Employee(var name : String = "", var surname : String = "")
class Developer(name : String = "", surname : String = "", var language : String =
"Kotlin"): Employee(name, surname)
class Architect(name : String = "", surname : String = ""): Employee(name, surname)
class Manager(name : String = "", surname : String = ""): Employee(name, surname)
//If a want a toJson() Method?
import com.google.gson.Gson;
abstract class Employee(var name : String = "", var surname : String = "") {
fun toJson() = Gson().toJson(this)
}
33. Extension Methods
import com.google.gson.Gson;
fun Employee.toJson() = Gson().toJson(this) //In a module, or in a class
fun Any.toJson() = Gson().toJson(this) //Better
//Even better, as a readonly property
val Employee.json
get() = Gson().toJson(this)
fun main(args : Array<String>) {
var d = Developer()
println(d.toJson())
}
What If Employee, Developer, Architect and Manager are read-only (in jar, in maven package, etc)?
43. Kotlin + jQuery
npm install ts2kt
ts2kt -d headers jquery.d.ts
Download jquery.d.ts from
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types/jquery/jquery.d.ts
@JsName("$")
public external fun jQuery(selector : String) : JQuery
$(“#dataTable”).asDynamic().datatable()
Of course you have to import your jQuery and lib scripts into html
44. Kotlin-Native
• Kotlin Source -> Compiler -> Platform Binary (NO VM Needed)
• Code Sharing Between Platforms
• Windows, iOS, Android, Linux, OS X, RaspberryPI
• Still Early Beta (0.3)
git clone https://github.com/JetBrains/kotlin-native.git
cd kotlin-native
.gradlew.bat dependencies-update
.gradlew.bat dist
.gradlew.bat cross_dist
.gradlew.bat backend.native:tests:run <- Optional takes a veeery long time to end
.distbinkotlinc HelloWorld.kt –o HelloWorld -opt