SlideShare ist ein Scribd-Unternehmen logo
1 von 97
© Instil Software 2017
September 2017
eamonn.boyle@instil.coeamonn.boyle@instil.cogarth.gilmour@instil.co | eamonn.boyle@instil.co
Kotlin as a Better Java
Cork Functional Programmers
and Cork Java Users Group
© Instil Software 2017
C
C++
Java
C#
Pascal
Delphi
Basic
Visual Basic
VB .NET
Perl
F#
Java
Script
CoffeeScript
1990
2000
2010
TypeScript
Jython
JRuby
PowerShell
Dart
Scala
Clojure
Kotlin
Groovy
Go
Objective C
Shell
Scripting
Swift
Python
Ruby
© Instil Software 2017
Scala
Kotlin Swift
© Instil Software 2017
TypeScript
© Instil Software 2017
The New Era of Programming Pt1
Everything is an object
Type inference
Functions
• Can be free
• Can be nested
• Can be single expression
• Can be lambdas
• Can be referenced
• Don’t return null
• Use lambda syntax for
inputs and outputs
© Instil Software 2017
The New Era of Programming Pt2
String interpolation
No field declarations
• Primary constructors
• Auto-properties
Collections
• Are unified
• Are really generic
• Include Tuples
• Include Ranges
• Support FP operations
© Instil Software 2017
2010: Work begins on Kotlin within JetBrains
2011: First public announcement on Kotlin
2012: Open sourced under Apache 2 license
2016: Version one released
2017: First class support on Android
A Kotlin Timeline
© Instil Software 2017
Kotlin On Other Platforms
JVM
Bytecode
Kotlin
(JS)
Kotlin
(Native)
Kotlin
(JVM)
Browser
Interpreter Runtime
OS
© Instil Software 2017
A Simple Case Study
© Instil Software 2017
Enter some numbers or three 'X' to finish
10
20
30
40
50
XXX
Total of numbers is: 150
Enter some numbers or three 'X' to finish
wibble
Ignoring wibble
12
13
14
XXX
Total of numbers is: 39
Enter some numbers or three 'X' to finish
XXX
Total of numbers is: 0
© Instil Software 2017
public class Program {
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
List<Integer> numbers = new ArrayList<>();
System.out.println("Enter some numbers or three 'X' to finish");
Pattern endOfInput = Pattern.compile("[X]{3}");
while(scanner.hasNextLine()) {
if(scanner.hasNextInt()) {
numbers.add(scanner.nextInt());
} else {
if(scanner.hasNext(endOfInput)) {
break;
} else {
String mysteryText = scanner.nextLine();
System.out.printf(“Ignoring %sn", mysteryText);
}
}
}
int total = numbers.stream().reduce((a,b) -> a + b).orElse(17);
System.out.printf("Total of numbers is: %sn",total);
}
}
java.demos.hello
A Sample Java Program
© Instil Software 2017
fun main(args: Array<String>) {
val numbers = mutableListOf<Int>()
val scanner = Scanner(System.`in`)
val endOfInput = Regex("[X]{3}")
println("Enter some numbers or three 'X' to finish")
while (scanner.hasNextLine()) {
if (scanner.hasNextInt()) {
numbers += scanner.nextInt()
} else {
if (scanner.hasNext(endOfInput.toPattern())) {
break
} else {
val mysteryText = scanner.nextLine()
println("Ignoring $mysteryText")
}
}
}
//simpler alternative is ‘numbers.sum()’
val total = numbers.fold(0,Int::plus)
println("Total of numbers is: $total")
}
kotlin.demos.hello
The Sample Re-Written in Kotlin
Points to note:
 No redundant class
 No semi-colons
 Type inference
 Both ‘val’ and ‘var’
 Helper functions
 String interpolation
 Simplified collections
 Interop with Java types
 Simpler use of FP
© Instil Software 2017
object NumbersDemo {
def main(args: Array[String]) {
var numbers = List[Int]()
val scanner = new Scanner(System.in)
val endOfInput = "[X]{3}".r
println("Enter some numbers or three 'X' to finish")
var notDone = true
while (scanner.hasNextLine() && notDone) {
if (scanner.hasNextInt()) {
numbers = scanner.nextInt() :: numbers
} else {
if (scanner.hasNext(endOfInput.pattern)) {
notDone = false
} else {
val mysteryText = scanner.nextLine()
println(s"Ignoring $mysteryText")
}
}
}
//show support for FP
val total1 = numbers.fold(0)(_ + _)
println(s"Total of numbers is: $total1")
//show simpler alternative in this case
val total2 = numbers.sum
println(s"Total of numbers is: $total2")
}
}
demos.scala
The Sample Rewritten in Scala
© Instil Software 2017
Feature Java 9 Kotlin Scala
Type Inference No Yes Yes
Unified Type System No Yes Yes
Protection from Null Results No Yes Yes
String Interpolation No Yes Yes
Extension Functions No Yes Partially
Inline Functions No Yes Yes
Primary Constructors No Yes Yes
Case / Data Classes No Yes Yes
Function Literals Yes Yes Yes
Local Functions No Yes Yes
Enclosure of local variables Partially Yes Yes
Single Expression Functions No Yes Yes
Tuples No Partially Yes
Monads No Partially Yes
Kotlin vs. Scala Comparison
© Instil Software 2017
Type Inference
© Instil Software 2017
class Person(val name: String)
fun main(args: Array<String>) {
val a = 123
val b = "ABC"
val c = "[A-Z]{3}".toRegex()
val d = 1..10
val e = Person("Jason")
val f = arrayOf(a, b, c, d, e)
f.forEach { println(it.javaClass.name) }
}
java.lang.Integer
java.lang.String
kotlin.text.Regex
kotlin.ranges.IntRange
basics.type.inference.Person
basics.type.inference.Program
Type Inference In Kotlin
© Instil Software 2017
Managing Null Pointers
© Instil Software 2017
A design goal for Kotlin was to minimise null pointer errors
• They cant be eliminated without affecting interoperability
The Kotlin compiler checks for nulls automatically
• It is not possible for a regular variable to be set to null
Every type you create has a nullable alternative
• Written as ‘String?’ for ‘String’ and ‘Person?’ for ‘Person’ etc…
• You can explicitly specify this but often it is inferred
Nullable types often occur in function signatures
• So ‘fun foo() Int’ cannot return null but ‘fun foo() Int?’ can
Managing Null Pointers in Kotlin
© Instil Software 2017
The ‘?.’ syntax makes a call only if the reference is not null
• So ‘foo?.bar()’ would only call ‘bar’ if ‘foo’ was not null
• Calls can be chained as required e.g. ‘foo?.bar().zed()’
The ‘?:’ syntax is used to specify a backup value
• So ‘foo()?: “bar”’ returns ‘bar’ if the LHS is null
• Note the RHS is only evaluated if required
The ‘!!.’ syntax is for when you want an exception
• For example when replacing a Java library with Kotlin whilst
preserving exactly the same behaviour
• So ‘foo||.bar()’ throws an exception if ‘foo’ is null
• The garishness of the operator makes it easy to spot
during pair programming and/or code reviews
Operators for Nullable Types
© Instil Software 2017
fun foo(input: Int) = if(input > 0) "abc" else "def" //return type is String
fun bar(input: Int) = if(input > 0) "abc" else null //return type is String?
fun main(args: Array<String>) {
val str1 = foo(12) //inferred type is String
val str2 = bar(34) //inferred type is String?
val str3: String = foo(12) //declared type is String
val str4: String? = bar(34) //declared type must be
String?
println(bar(12)?.toUpperCase()) //safe call operator (success)
println(bar(-12)?.toUpperCase()) //safe call operator (failure)
println(bar(12)?: "wibble") //elvis operator (success)
println(bar(-12)?: "wibble") //elvis operator (failure)
println(bar(12)!!.toUpperCase()) //NPE operator (success)
try {
println(bar(-12)!!.toUpperCase()) //NPE operator (failure)
} catch(ex: Throwable) {
println("Finally a NPE :-)")
}
}
basics.safety.Program
Managing Null Pointers in Kotlin
ABC
null
abc
wibble
ABC
Finally a NPE :-)
© Instil Software 2017
fun demo1(input: Int) {
println("Demo1 called with $input")
}
fun demo2(input: Int): Unit { //same as above
println("Demo2 called with $input")
}
fun demo3(input: Int): String = "Demo3 called with $input"
fun demo4(input: Int): String {
return "Demo4 called with $input"
}
fun demo5(input: Int = 456): String {
return "Demo5 called with $input"
}
fun demo6(vararg input:Int) = input.reduce { a,b -> a + b}
fun demo7(port: Int, timeout:Int, retries: Int): String {
return “““Trying to connect on port $port
with $retries retries and a timeout of $timeout
”””
}
basics.functions.Program.kt
Function Declarations
© Instil Software 2017
fun main(args: Array<String>) {
demo1(123)
demo2(123)
println(demo3(123))
println(demo4(123))
println(demo5(123))
println(demo5())
println("Adding numbers gives: ${demo6(10,20,30,40,50)}")
println(demo7(timeout = 60, port=8080, retries = 10))
}
basics.functions.Program.kt
Demo1 called with 123
Demo2 called with 123
Demo3 called with 123
Demo4 called with 123
Demo5 called with 123
Demo5 called with 456
Adding numbers gives: 150
Trying to connect on port 8080
with 10 retries and a timeout of 60
Function Declarations
© Instil Software 2017
A Kotlin function can be declared as infix
• This allows it to be used as if it were a keyword
• E.g. ‘12 downTo 1’ is the same as ‘12.downTo(1)’
• An infix function must follow some simple rules:
• It can only take a single parameter
• It must be a member of a type (i.e. a method)
• Or an extension to an existing type
• It must be declared using the ‘infix’ keyword
It is possibly to pass references to functions and anonymous
functions (aka lambdas) as parameters
Special Kinds Of Function
© Instil Software 2017
class Number(val value: Int) {
infix fun plus(input: Int): Number {
return Number(value + input)
}
infix fun minus(input: Int): Number {
return Number(value - input)
}
fun forEach(action: (Int) -> Unit) {
for(x in 1..value) {
action(x)
}
}
}
fun main(args: Array<String>) {
val num1 = Number(5)
val num2 = num1 plus 7
val num3 = num2 minus 3
num1.forEach { print("$it ")}
println()
num2.forEach { print("$it ")}
println()
num3.forEach { print("$it ")}
}
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 7 8 9
basics.functions.infix
Special Function Declarations
© Instil Software 2017
Classes in Kotlin
© Instil Software 2017
When coding in Kotlin we think in terms of properties
• In Kotlin it isn’t possible to manually add fields to a class
• Instead you add properties, which are public by default
When you add a property to a class Kotlin will:
• Declare a ‘backing field’ of the appropriate type
• Declare a standard Java getter method
• Unless the property has been declared private
• Declare a standard Java setter method
• Assuming the property has been declared with ‘var’
Accessor methods are automatically invoked for you
• So ‘val wage = emp.salary’ is ‘val wage = emp.getSalary()’
• Similarly ‘emp.salary = n’ becomes ‘emp.setSalary(n)’
Classes and Properties in Kotlin
© Instil Software 2017
class Person {
var name: String = "Dave"
fun sayHello() = println("Hello $name")
}
fun main(args: Array<String>) {
val p = Person()
println(p.name)
p.sayHello()
p.name = "Jane"
println(p.name)
p.sayHello()
}
oo.properties
javap -p oo.properties.Person
Compiled from "Person.kt"
public final class oo.properties.Person {
private java.lang.String name;
public final java.lang.String getName();
public final void setName(java.lang.String);
public final void sayHello();
public oo.properties.regular.Person();
}
Classes and Properties in Kotlin
Dave
Hello Dave
Jane
Hello Jane
Note Kotlin does
not require ‘new’
© Instil Software 2017
Classes and Properties in Kotlin
$ javap -p -c oo.properties.regular.PersonKt
Compiled from "Person.kt"
public final class oo.properties.regular.PersonKt {
public static final void main(java.lang.String[]);
Code:
0: aload_0
1: ldc #9 // String args
3: invokestatic #15 // Method …/Intrinsics.checkParameterIsNotNull:(…)V
6: new #17 // class oo/properties/regular/Person
9: dup
10: invokespecial #21 // Method oo/properties/regular/Person."<init>":()V
13: astore_1
14: aload_1
15: invokevirtual #25 // Method oo/properties/regular/Person.getName:()Ljava/lang/String;
18: astore_2
19: getstatic #31 // Field java/lang/System.out:Ljava/io/PrintStream;
22: aload_2
23: invokevirtual #37 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
26: aload_1
27: invokevirtual #40 // Method oo/properties/regular/Person.sayHello:()V
30: aload_1
31: ldc #42 // String Jane
33: invokevirtual #46 // Method oo/properties/regular/Person.setName:(Ljava/lang/String;)V
36: aload_1
37: invokevirtual #25 // Method oo/properties/regular/Person.getName:()Ljava/lang/String;
40: astore_2
41: getstatic #31 // Field java/lang/System.out:Ljava/io/PrintStream;
44: aload_2
45: invokevirtual #37 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
48: aload_1
49: invokevirtual #40 // Method oo/properties/regular/Person.sayHello:()V
52: return
}
© Instil Software 2017
The default accessor methods can be overridden
• By providing ‘get’ and/or ‘set’ blocks after the declaration
• The backing field can be accessed via the keyword ‘field’
• Note this is only allowed within the ‘get/set’ blocks
This is useful in two scenarios:
• When you want to base a property on an expression
• Such as the ‘empty’ property of a custom collection
• When you want to add validation rules
• E.g. the setter method for a ‘wage’ property could check if
the new value was within the salary band of the employee
Customising Properties
© Instil Software 2017
fun main(args: Array<String>) {
val p = Person()
p.sayHello()
p.name = "Jane"
p.sayHello()
}
class Person {
var name: String = "Dave"
get() = "[$field]"
set(value) { field = "$value Jones" }
fun sayHello() = println("Hello $name")
}
oo.properties.customized
Hello [Dave]
Hello [Jane Jones]
Customising Properties
© Instil Software 2017
Kotlin provides a feature called ‘primary constructors’
• Also available in Scala and TypeScript and coming in C#
The class and constructor declarations are merged
• Removing the need to retype the class name, introduce extra
braces and both declare and initialize fields manually
The way the parameters are declared is crucial
• If declared without ‘var’ or ‘val’ they are normal inputs
• No extra members will be added to the class
• If declared with var / val then fields and properties are added
• When ‘val’ is used only a getter method is created
The properties will be public by default
• You can alter this by adding an access modifier
Kotlin and Primary Constructors
© Instil Software 2017
package oo.basics
class Person(name: String, age: Int)
oo.basics
javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
Here the parameters lack ‘val’ or
‘var’ so no fields or properties are
created.
© Instil Software 2017
package oo.basics
class Person(val name: String, val age: Int)
oo.basics
$ javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String name;
private final int age;
public final java.lang.String getName();
public final int getAge();
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
Adding ‘val’ to the parameters means that a
backing field will be created, initialised and
accessible via a ‘getter’ method
© Instil Software 2017
package oo.basics
class Person(var name: String, var age: Int)
oo.basics
Compiled from "Person.kt”
public final class oo.basics.Person {
private java.lang.String name;
private int age;
public final java.lang.String getName();
public final void setName(java.lang.String);
public final int getAge();
public final void setAge(int);
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
Using ‘var’ instead of ‘val’ means that the
compiler also generates ‘setter’ methods
© Instil Software 2017
package oo.basics
class Person(val name: String, var age: Int)
oo.basics
$ javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String name;
private int age;
public final java.lang.String getName();
public final int getAge();
public final void setAge(int);
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
There is no issue with using both ‘val’ and ‘var’ on
different parameters. Note the default access is public.
© Instil Software 2017
package oo.basics
class Person(public val name: String, protected var age: Int)
oo.basics
$ javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String name;
private int age;
public final java.lang.String getName();
protected final int getAge();
protected final void setAge(int);
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
Adding ‘public’ to the ‘name’ field will have no effect as that is the default.
Adding ‘protected’ to ‘age’ will change the access level of the methods but
we would need to declare the class ‘open’ for this to be useful
© Instil Software 2017
package oo.basics
class Person(public val name: String, private var age: Int)
oo.basics
javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String name;
private int age;
public final java.lang.String getName();
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
Declaring a parameter as private causes the
backing field to be created but not the accessor
methods.
© Instil Software 2017
package oo.basics
class Person(private val name: String, private var age: Int)
oo.basics
$ javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String name;
private int age;
public oo.basics.Person(java.lang.String, int);
}
Understanding Primary Constructors
There is no issue with all the
parameters being private
© Instil Software 2017
package oo.basics
class Person(val name: String, val age: Int) {
private val address = "10 Arcatia Road"
init {
println("Person object created")
}
}
oo.basics
javap -p -c oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private final java.lang.String address;
private final java.lang.String name;
private final int age;
public final java.lang.String getName();
public final int getAge();
public oo.basics.Person(java.lang.String, int);
--------- Earlier code omitted ---------
21: ldc #8 // String 10 Arcatia Road
23: putfield #36 // Field address:Ljava/lang/String;
26: ldc #38 // String Person object created
28: astore_3
29: getstatic #44 // Field java/lang/System.out:Ljava/io/PrintStream;
32: aload_3
33: invokevirtual #50 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
36: return
}
Understanding Primary Constructors
© Instil Software 2017
package oo.basics
class Person(val name: String, val age: Int) {
private var address = "10 Arcatia Road"
init {
println("Person object created")
}
constructor(name: String, age: Int, address: String) : this(name,age) {
println("Secondary constructor called")
this.address = address;
}
}
oo.secondary.constructors
$ javap -p oo.basics.Person
Compiled from "Person.kt"
public final class oo.basics.Person {
private java.lang.String address;
private final java.lang.String name;
private final int age;
public final java.lang.String getName();
public final int getAge();
public oo.basics.Person(java.lang.String, int);
public oo.basics.Person(java.lang.String, int, java.lang.String);
}
Adding Secondary Constructors
© Instil Software 2017
Kotlin adds the following to data classes:
• The familiar ‘equals’ and ‘hashCode’ methods
• A straightforward implementation of ‘toString’
• Which returns output of type ‘Foo(bar=123, zed=“abc”)’
• A ‘copy’ method which returns a clone of the object
• Component methods for destructuring (see later)
The ‘copy’ method allows you to make changes
• By default the properties of the copy are set to the same
values as the original, but you can alter them if you like
• E.g. ‘val person2 = person1.copy(age=28)’
Declaring Data Classes
© Instil Software 2017
fun main(args: Array<String>) {
val emp1 = Employee("Dave Jones", "10 Arcatia Road", 30000.0)
val emp2 = Employee("Dave Jones", "10 Arcatia Road", 30000.0)
println(emp1)
println(emp2)
println(emp1 === emp2)
println(emp1 == emp2)
println(emp1.equals(emp2))
println(emp1.hashCode())
println(emp2.hashCode())
val emp3 = emp2.copy(salary = 40000.0)
println(emp3)
}
data class Employee(val name: String, val address: String, val salary: Double)
oo.entities
Declaring Data Classes
Employee(name=Dave Jones, address=10 Arcatia Road, salary=30000.0)
Employee(name=Dave Jones, address=10 Arcatia Road, salary=30000.0)
false
true
true
1296289951
Employee(name=Dave Jones, address=10 Arcatia Road, salary=40000.0)
1296289951
© Instil Software 2017
Generics
© Instil Software 2017
Generics in Kotlin
fun thoughtExperiment() {
val myList = LinkedList<Manager>()
foobar(myList) //should this be allowed?
}
fun foobar(input: LinkedList<Employee>) {
input.add(Employee(“Dave”))
}
© Instil Software 2017
We can simplify our problem by restricting the generic type
• A read-only list would solve the current problem
• We could pass in a list of any subtype of ‘Employee’
• Since the methods of the list could not accept instances of
‘T’ there would be no danger of adding the wrong type
• A write-only list might be useful as well
• ‘fun foobar(input: WriteOnlyList<Manager>)’ could be
called with a write-only list of ‘Employee’ or ‘Person’
• Since ‘input.add(Manager(“Jane”))’ works in all cases
• Assuming that Manager  Employee  Person
Generics in Kotlin
© Instil Software 2017
Kotlin allows you to restrict generic types in this way
• Saying ‘out T’ means that ‘T’ objects can only be returned
• Saying ‘in T’ means that ‘T’ object can only be accepted
• This is referred to as ‘Declaration Site Type Variance’
Generics in Kotlin
© Instil Software 2017
open class Employee
open class Manager : Employee()
open class Director : Manager()
class ReadWriteList<T> {
fun get(index: Int) : T? = null
fun findFirst(p: (T) -> Boolean) : T? = null
fun findAll(p: (T) -> Boolean) : ReadWriteList<T>? = null
fun add(item: T) {}
fun add(index: Int, item: T) {}
fun addAll(items: ReadWriteList<T>) {}
}
class ReadOnlyList<out T> {
fun get(index: Int) : T? = null
fun findFirst(p: (T) -> Boolean) : T? = null
fun findAll(p: (T) -> Boolean) : ReadOnlyList<T>? = null
}
class WriteOnlyList<in T> {
fun add(item: T) {}
fun add(index: Int, item: T) {}
fun addAll(vararg items: T) {}
}
generics.declaration.site.variance.Program.kt
Generics in Kotlin
© Instil Software 2017
fun demo1(input: ReadWriteList<Manager>) {
input.add(Manager()) //this is not controversial
input.add(Director()) //this surprises most people
}
fun demo2(input: ReadOnlyList<Manager>) {
//can only access items here
}
fun demo3(input: WriteOnlyList<Manager>) {
//can only insert items here
}
fun main(args: Array<String>) {
//demo1(ReadWriteList<Employee>()) //will not compile
demo1(ReadWriteList<Manager>())
//demo1(ReadWriteList<Director>()) //will not compile
//demo2(ReadOnlyList<Employee>()) //will not compile
demo2(ReadOnlyList<Manager>())
demo2(ReadOnlyList<Director>())
demo3(WriteOnlyList<Employee>())
demo3(WriteOnlyList<Manager>())
//demo3(WriteOnlyList<Director>()) //will not compile
}
generics.declaration.site.variance.Program.kt
Generics in Kotlin
© Instil Software 2017
When we say ‘class Foo<out T>’ then:
• A function which takes a ‘Foo<Manager>’ will also accept a
‘Foo<Director>’ or any other subtype (such as ‘Foo<CTO>’)
• Hence the possible set of valid values is infinite
• This is because ‘Foo’ is acting as a producer and a reference
of type Manager can refer to any instance of any subtype
• We say that in this case ‘T’ is covariant
When we say ‘class Foo<in T>’ then:
• A function which takes a ‘Foo<Manager>’ will also accept
either a ‘Foo<Employee>’ or a ‘Foo<Any>’
• This time the set of valid values is fixed
• This is because ‘Foo’ acts as a consumer and an input of
‘Manager’ can be stored via a ref of ‘Employee’ or ‘Any’
• We say that in this case ‘T’ is contravariant
Understanding Declaration Site Variance
© Instil Software 2017
Declaration site variance is not always sufficient
• Consider a function which takes two lists of type ‘Employee’
and where we want to transfer items between the lists
• The compiler needs to be able to check, on a call by call
basis, whether the operations we intend to perform are safe
• E.g. it could be called in one place with lists of ‘Employee’
and ‘Manager’ and in another with ‘CTO’ and ‘Director’
We simplify the compilers job by using the ‘in’ and ‘out’
modifiers directly on the parameters to the function
• E.g. fun demo(p1: MyList<out Thing>, p2: MyList<in Thing>)
• This allows the compiler to validate the code in the function
and determine whether a given call should be permitted
• It is known as ‘use-site variance’ or ‘type projection’
Understanding Use Site Variance
© Instil Software 2017
fun copyFirstTen(input: ReadWriteList<out Employee>,
output: ReadWriteList<in Employee>) {
//try to copy first 10 items
for(x in 0..9) {
val item = input.get(x)
if(item != null) {
output.add(item)
}
}
}
fun main(args: Array<String>) {
val tst1 = ReadWriteList<Employee>()
val tst2 = ReadWriteList<Manager>()
val tst3 = ReadWriteList<Director>()
copyFirstTen(tst1,tst1) //fine
copyFirstTen(tst2,tst1) //fine
copyFirstTen(tst3,tst1) //fine
//copyFirstTen(tst1,tst2) //will not compile
//copyFirstTen(tst1,tst3) //will not compile
}
generics.use.site.variance.Program.kt
Generics in Kotlin
© Instil Software 2017
So far we have assumed our code can be fully generified
• We can rewrite our ‘LinkedList’ of string as ‘LinkedList<T>’
and it will then automatically work for all possible values of ‘T’
This is (mostly) true of collections but false in other cases
• Often we find code which can only be partially generified
• For example it might only work for any type which has a
‘compareTo’ method, or which implements ‘Iterable’
Generic Constraints allow us to state this in code
• For example the function ‘fun <T: Iterable> foobar(p: T)’ can
be invoked with any type which implements ‘Iterable’
• As in Java this is referred to as an ‘upper bound’
Generic Constraints in Kotlin
© Instil Software 2017
open class Employee {
fun work() {}
}
open class Manager : Employee() {
fun manage() {}
}
open class Director : Manager() {
fun direct() {}
}
fun <T> demo1(input: T) {
println(input.toString())
}
fun <T : Employee> demo2(input: T) {
input.work()
}
fun <T : Manager> demo3(input: T) {
input.work()
input.manage()
}
fun <T : Director> demo4(input: T) {
input.work()
input.manage()
input.direct()
}
generics.constraints.Program
Generic Constraints
© Instil Software 2017
fun main(args: Array<String>) {
demo1(Employee())
demo1(Manager())
demo1(Director())
demo2(Employee())
demo2(Manager())
demo2(Director())
//demo3(Employee()) // Will not compile
demo3(Manager())
demo3(Director())
//demo4(Employee()) // Will not compile
//demo4(Manager()) // Will not compile
demo4(Director())
}
generics.constraints.Program
Generic Constraints
© Instil Software 2017
It is possible to specify multiple generic constraints
• Useful when a type needs to implement multiple interfaces
• E.g. a type might need to be both serializable and cloneable
Multiple constraints use a different syntax
• The function declaration ends in a ‘where’ clause, whose
value is a series of constraints on the type parameter(s)
Generic Constraints in Kotlin
© Instil Software 2017
interface Edible {
fun eat()
}
interface Drinkable {
fun drink()
}
class Pie : Edible {
override fun eat() {}
}
class Ale : Drinkable {
override fun drink() {}
}
class Ramen : Edible, Drinkable {
override fun eat() {}
override fun drink() {}
}
demos.constraints.generics.multiple.Program
Generic Constraints in Kotlin
© Instil Software 2017
fun <T> demo(input: T) where T: Edible,
T: Drinkable {
input.eat()
input.drink()
}
fun main(args: Array<String>) {
//demo(Pie()) // Will not compile
//demo(Ale()) // Will not compile
demo(Ramen())
}
demos.constraints.generics.multiple.Program
Generic Constraints in Kotlin
© Instil Software 2017
Collections
© Instil Software 2017
Kotlin provides data structures via ‘kotlin.collections’
• As in Java, arrays are not part of the collections library
• Support for arrays is provided in the core ‘kotlin’ package
Collections are typically created indirectly
• Via methods such as ‘emptyList’ and ‘listOf’
Both mutable and immutable collections are provided
• ‘listOf’ provides a list where adding returns a new collection
• ‘mutableListOf’ provides a list whose state can be changed
At present everything is implemented via JSE collections
• So you are given a read-only view of a mutable collection
Collections in Kotlin
© Instil Software 2017
fun printList(input: List<Int>) {
println("This is a list of type ${input.javaClass.name}")
if(input.isEmpty()) {
println("tThe list is empty")
} else {
val content = input.fold(""){a,b -> a + b + " "}
println("tThe list holds: $content")
}
}
fun main(args: Array<String>) {
val list1: List<Int> = emptyList()
val list2 = emptyList<Int>()
val list3 = listOf(12)
val list4 = listOf(12,34,56)
val list5 = mutableListOf(12,34,56)
printList(list1)
printList(list2)
printList(list3)
printList(list4)
printList(list5)
collections.basic.Program
Introducing Kotlin Collections
© Instil Software 2017
val list6 = list4.plus(78)
list5.add(78)
println("-------------")
printList(list4)
printList(list5)
printList(list6)
}
collections.basic.Program
This is a list of type kotlin.collections.EmptyList
The list is empty
This is a list of type kotlin.collections.EmptyList
The list is empty
This is a list of type java.util.Collections$SingletonList
The list holds: 12
This is a list of type java.util.Arrays$ArrayList
The list holds: 12 34 56
This is a list of type java.util.ArrayList
The list holds: 12 34 56
-------------
This is a list of type java.util.Arrays$ArrayList
The list holds: 12 34 56
This is a list of type java.util.ArrayList
The list holds: 12 34 56 78
This is a list of type java.util.ArrayList
The list holds: 12 34 56 78
Introducing Kotlin Collections
List 4 was not
modified by the
call to ‘plus’
© Instil Software 2017
Example Types from the Collections Hierarchy
Iterable
Collection
MutableCollectionList
MutableList
AbstractMutableList
ArrayList
RandomAcces
s
java.util.AbstractList
listOf
emptyList
arrayListOf
mutableListOf
© Instil Software 2017
fun main(args: Array<String>) {
val myList = listOf("ab","cd","ef")
println(myList.elementAtOrElse(0, {"Nothing at $it"}))
println(myList.elementAtOrElse(3, {"Nothing at $it"}))
val sb = StringBuilder()
myList.joinTo(buffer = sb,separator = " ", prefix=">>", postfix="<<")
println(sb)
val myList2 = myList.reversed()
println(myList2)
}
collections.functions.Program
ab
Nothing at 3
>>ab cd ef<<
[ef, cd, ab]
Accessing Values in Collections
© Instil Software 2017
Kotlin provides support for destructuring
• I.e. retrieving multiple values from a collection at once
• This is often found in scripting languages but rare elsewhere
The syntax is ‘val (a,b,c) = myThing’
• If ‘myThing’ is a list this will be compiled as calls to ‘get’
• Otherwise the compiler will expect there to be methods of the
form ‘componentN’ and create declarations as below
Destructuring in Collections
val a = myList.component1()
val b = myList.component2()
val c = myList.component3()
© Instil Software 2017
fun main(args: Array<String>) {
var myList = listOf(12,34,56)
var myPair = Pair(12,"ab")
var (a,b,c) = myList
var (d,e) = myPair
println("List values are ${a}, ${b} and ${c}")
println("Pair values are ${d} and ${e}")
}
collections.destructuring.Program
List values are 12, 34 and 56
Pair values are 12 and ab
Destructuring in Collections
© Instil Software 2017
Destructing In Collections
javap -p -c collections.destructuring.ProgramKt
Compiled from "Program.kt"
public final class collections.destructuring.ProgramKt {
public static final void main(java.lang.String[]);
Code:
63: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
68: checkcast #43 // class java/lang/Number
71: invokevirtual #47 // Method java/lang/Number.intValue:()I
82: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
87: checkcast #43 // class java/lang/Number
90: invokevirtual #47 // Method java/lang/Number.intValue:()I
102: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
107: checkcast #43 // class java/lang/Number
110: invokevirtual #47 // Method java/lang/Number.intValue:()I
123: invokevirtual #51 // Method kotlin/Pair.component1:()Ljava/lang/Object;
126: checkcast #43 // class java/lang/Number
129: invokevirtual #47 // Method java/lang/Number.intValue:()I
136: invokevirtual #54 // Method kotlin/Pair.component2:()Ljava/lang/Object;
139: checkcast #56 // class java/lang/String
Calls to ‘get’ method
Calls to ‘componentN’ methods
© Instil Software 2017
Functional Programming
© Instil Software 2017
The ‘map’ function converts a list of ‘T’ to a list of ‘U’
• Based on a mapping function that you provide
The ‘filter’ function produces a smaller list
• Based on a predicate function that you provide
The ‘partition’ function is similar to filter
• But it sorts the items into two separate lists based on the test
The ‘Functional Toolkit’
fun <T,U>map(input: List<T>,
mappingFunc: (T)->U): List<U> { … }
fun <T>filter(input: List<T>,
filterFunc: (T)->Boolean): List<T> { … }
fun <T>partition(input: List<T>, filterFunc: (T)->Boolean):
Pair<List<T>,List<T>> {
© Instil Software 2017
fun <T,U>map(input: List<T>, mappingFunc: (T)->U): List<U> {
val results = ArrayList<U>()
for(item in input) {
results.add(mappingFunc(item));
}
return results
}
fun <T>filter(input: List<T>, filterFunc: (T)->Boolean): List<T> {
val results = ArrayList<T>()
for(item in input) {
if(filterFunc(item)) {
results.add(item);
}
}
return results
}
fun <T>partition(input: List<T>, filterFunc: (T)->Boolean): Pair<List<T>,List<T>> {
val results = Pair(ArrayList<T>(),ArrayList<T>())
for(item in input) {
if(filterFunc(item)) {
results.first.add(item);
} else {
results.second.add(item);
}
}
return results
}
coding.the.functional.toolkit
Implementing the ‘Functional Toolkit’ By Hand
© Instil Software 2017
fun main(args: Array<String>) {
val originalData = arrayListOf<String>("12","34","56","78","90")
val mappedData = map(originalData, String::toInt)
val filteredData = filter(mappedData) { it > 50 }
val partitionedData = partition(mappedData) { it > 50 }
printResults("Results of mapping",mappedData)
printResults("Results of filtering", filteredData)
printResults("Results of partitioning", partitionedData)
}
fun<T> printResults(title: String, input: List<T>) {
println("----- $title -----")
for(item in input) {
println("t$item")
}
}
fun<T,U> printResults(title: String, input: Pair<List<T>,List<U>>) {
println("----- $title -----")
println("tfirst items in pair")
for(item in input.first) {
println("tt$item")
}
println("tsecond items in pair")
for(item in input.second) {
println("tt$item")
}
}
coding.the.functional.toolkit
Implementing the ‘Functional Toolkit’ By Hand
© Instil Software 2017
Implementing the ‘Functional Toolkit’ By Hand
----- Results of mapping -----
12
34
56
78
90
----- Results of filtering -----
56
78
90
----- Results of partitioning -----
first items in pair
56
78
90
second items in pair
12
34
© Instil Software 2017
Higher level functions can also return new functions
• Functional coders never implement a ‘family’ of functions
• Instead they create a function that returns the one they
currently need, plus as many variants as required
A simple example is wrapping text in HTML tags
• We could define one wrapper function per tag
• This would be tedious and require periodic updates
• We could write a function that took the tag name
• But this would be ‘stringly typed code’ and prone to typos
• We could write a function that takes a tag name and returns a
function that takes arbitrary text and wraps it in the tag
• This prevents us having to build and maintain a library of
trivial functions whilst also protecting against simple errors
Using Functions as Outputs
© Instil Software 2017
fun wrapInH1(input: String) = "<h1>$input</h1>"
fun wrapInH2(input: String) = "<h2>$input</h2>"
fun wrapInTag(tagName: String, input: String): String {
val openingTag = "<$tagName>"
val closingTag = "</$tagName>"
return "$openingTag$input$closingTag"
}
fun buildWrapper(tagName: String): (String) -> String {
val openingTag = "<$tagName>"
val closingTag = "</$tagName>"
return { "$openingTag$it$closingTag" }
}
functions.returning.functions
Using Functions as Outputs
© Instil Software 2017
fun main(args: Array<String>) {
println(wrapInH1("Marge"))
println(wrapInH2("Homer"))
println(wrapInTag("h3","Liza"))
println(wrapInTag("h4","Bart"))
val wrapInBold = buildWrapper("b")
val wrapInItalics = buildWrapper("i")
val wrapInMark = buildWrapper("mark")
println(wrapInBold("Maggie"))
println(wrapInItalics("Snowball III"))
println(wrapInMark("Santas Little Helper"))
}
functions.returning.functions
<h1>Marge</h1>
<h2>Homer</h2>
<h3>Liza</h3>
<h4>Bart</h4>
<b>Maggie</b>
<i>Snowball III</i>
<mark>Santas Little Helper</mark>
Using Functions as Outputs
© Instil Software 2017
In the previous example we returned a function literal
• This worked well but in more complex cases we will be
returning functions that contain larger quantities of code
Instead we can return a reference to a local function
• Functional languages like Kotlin allow functions to be nested
within one another and these local functions to be returned
In the following example we create ‘buildMatcher’ which:
• Takes a regular expression in string format as its input
• Builds and returns a function that takes some text and returns
all the matches for the regular expression as a list of strings
Returning Local Functions
© Instil Software 2017
import kotlin.text.Regex
fun main(args: Array<String>) {
val data = "abcDEFghiJKLmnpPQRstuVWXyz"
val matcher1 = buildMatcher("[A-Z]{3}")
val matcher2 = buildMatcher("[a-z]{2,3}")
println("First matches are:")
for(str in matcher1(data)) {
println("t$str")
}
println("Second matches are:")
for(str in matcher2(data)) {
println("t$str")
}
}
fun buildMatcher(pattern: String): (String) -> Sequence<String> {
fun matcher(text: String): Sequence<String> {
val regex = Regex(pattern)
return regex.findAll(text)
.map { it.value }
}
return ::matcher
}
returning.functions
Returning Local Functions
© Instil Software 2017
Returning Local Functions
First matches are:
DEF
JKL
PQR
VWX
Second matches are:
abc
ghi
mnp
stu
yz
© Instil Software 2017
Functional Collections
© Instil Software 2017
Kotlin collections offer the standard ‘functional toolkit’
• A summary of these operations is provided below
• Remember you can add your own via extensions
In the following example we:
• Create a list of course objects with associated instructors
• Query the data in increasingly complex ways
The Built In Functional Toolkit
Operation Name Description
all, any,name Perform a test using a predicate
first, filter, find, last Locate elements based on a predicate
map, flatMap Transform the elements in a collection
fold, foldRight, reduce, reduceRight Build a single value based on the elements
groupBy, associateBy Group the elements based on a key selector
© Instil Software 2017
data class Course(
val id: String,
val title: String,
val courseType: CourseType,
val duration: Int,
val instructors: List<Trainer>)
data class Trainer(
val name: String,
val rate: Double,
val skills : List<String>)
enum class CourseType {
BEGINNER,
INTERMEDIATE,
ADVANCED
}
functional.using.the.toolki
t
Using the Functional Toolkit
© Instil Software 2017
fun buildData(): List<Course> {
val dave = Trainer("Dave Jones", 500.0, arrayListOf("SQL","Perl","PHP"))
val jane = Trainer("Jane Smith", 750.0, arrayListOf("SQL","Java","JEE"))
val pete = Trainer("Pete Hughes", 1000.0, arrayListOf("Java", "JEE", "C#", "Scala"))
val mary = Trainer("Mary Donaghy", 1250.0, arrayListOf("Java", "JEE", "C#", "C++"))
return arrayListOf(
Course("AB12","Intro to Scala",BEGINNER,4,arrayListOf(pete)),
Course("CD34","JEE Web Development",INTERMEDIATE,3,arrayListOf(pete, mary, jane)),
Course("EF56","Meta-Programming in Ruby",ADVANCED,2,arrayListOf()),
Course("GH78","OO Design with UML",BEGINNER,3,arrayListOf(jane,pete,mary)),
Course("IJ90","Database Access with JPA",INTERMEDIATE,3, arrayListOf(jane)),
Course("KL12","Design Patterns in C#",ADVANCED,2, arrayListOf(pete,mary)),
Course("MN34","Relational Database Design",BEGINNER,4, arrayListOf(jane, dave)),
Course("OP56",”MySql Stored Procedures",INTERMEDIATE,1, arrayListOf(jane, dave)),
Course("QR78",”Parallel Programming",ADVANCED,2, arrayListOf(pete,mary)),
Course("ST90","C++ Programming for Beginners",BEGINNER,5,arrayListOf(mary)),
Course("UV12","UNIX Threading with PThreads",INTERMEDIATE,2,arrayListOf()),
Course("WX34","Writing Linux Device Drivers",ADVANCED,3,arrayListOf(mary)))
}
functional.using.the.toolki
t
Using the Functional Toolkit
© Instil Software 2017
fun main(args: Array<String>) {
val data = buildData()
titlesOfCourses(data)
titlesOfCoursesWithoutATrainer(data)
namesAndRatesOfTrainers(data)
theNumberOfAdvancedCourses(data)
totalDurationsOfBeginnerAndNonBeginnerCourses(data)
everyPairOfTrainersThatCouldDeliverJava(data)
possibleCostsOfJeeWebDevelopment(data)
coursesIdsAndTitlesGroupedByType(data)
}
functional.using.the.toolki
t
Using the Functional Toolkit
© Instil Software 2017
fun printTabbed(input: Any) = println("t$input")
fun printTitle(title: String) = println(title)
fun printLine() = println("--------")
//An extension function to return pairs of items without duplicates
// note this is the simplest possible implementation
fun List<String>.combinations(): List<Pair<String,String>> {
val results = ArrayList<Pair<String,String>>()
for(str1 in this) {
for(str2 in this) {
if(!str1.equals(str2)) {
if(!results.contains(Pair(str2,str1))) {
results.add(Pair(str1, str2))
}
}
}
}
return results
}
functional.using.the.toolki
t
Using the Functional Toolkit
© Instil Software 2017
fun titlesOfCourses(courses: List<Course>) {
printTitle("Titles of courses:")
courses.map { it.title }
.forEach(::printTabbed)
printLine()
}
fun titlesOfCoursesWithoutATrainer(courses: List<Course>) {
printTitle("Titles of courses without a trainer:")
courses.filter { it.instructors.isEmpty() }
.map { it.title }
.forEach(::printTabbed)
printLine()
}
fun namesAndRatesOfTrainers(courses: List<Course>) {
printTitle("Names and rates of trainers:")
courses.flatMap { it.instructors }
.toSet()
.map { Pair(it.name,it.rate)}
.forEach(::printTabbed)
printLine()
}
functional.using.the.toolkit
Using the Functional Toolkit
© Instil Software 2017
fun theNumberOfAdvancedCourses(courses: List<Course>) {
printTitle("The number of advanced courses:")
printTabbed(courses.count {it.courseType == ADVANCED})
printLine()
}
fun totalDurationsOfBeginnerAndNonBeginnerCourses(courses: List<Course>) {
printTitle("Total days for both beginner and non-beginner courses")
val splitCourses = courses.partition {it.courseType == BEGINNER}
val beginnerDuration = splitCourses.first.map{it.duration}.sum()
val nonBeginnerDuration = splitCourses.second.map{it.duration}.sum()
printTabbed(Pair(beginnerDuration,nonBeginnerDuration))
printLine()
}
fun everyPairOfTrainersThatCouldDeliverJava(courses: List<Course>) {
printTitle("Pairs of trainers that could deliver Java")
courses.flatMap {it.instructors}
.distinct()
.filter {it.skills.contains("Java")}
.map {it.name}
.combinations()
.forEach {printTabbed("${it.first} and ${it.second}")}
printLine()
}
functional.using.the.toolkit
Using the Functional Toolkit
© Instil Software 2017
fun possibleCostsOfJeeWebDevelopment(courses: List<Course>) {
printTitle("Possible costs of 'JEE Web Development'")
val course = courses.find {it.title.equals("JEE Web Development")}
val duration = course?.duration ?: 0
val namesAndCosts = course?.instructors
?.map { Pair(it.name, it.rate * duration)}
namesAndCosts?.forEach(::printTabbed)
printLine()
}
fun coursesIdsAndTitlesGroupedByType(courses: List<Course>) {
fun process(entry: Entry<CourseType, List<Course>>) {
printTabbed(entry.key)
entry.value.forEach { println("tt${it.id} ${it.title}")}
}
printTitle("Course ID's and titles grouped by type")
courses.groupBy {it.courseType}
.forEach(::process)
}
functional.using.the.toolkit
Using the Functional Toolkit
© Instil Software 2017
TDD Demonstration
© Instil Software 2017
Spring Demonstration
© Instil Software 2017
Creating a Spring Boot Project
Key details
Dependencies
Build tool choice
Language choice
© Instil Software 2017
Android Demonstration
© Instil Software 2017
© Instil Software 2017
© Instil Software 2017
© Instil Software 2017
Conclusions
© Instil Software 2017
Conclusions
Kotlin is the ideal language for
the JVM today
© Instil Software 2017
Conclusions
Will it be so tomorrow?
© Instil Software 2017
Conclusions

Weitere ähnliche Inhalte

Was ist angesagt?

Java 8 - CJ
Java 8 - CJJava 8 - CJ
Java 8 - CJSunil OS
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldJorge Vásquez
 
JavaScript Programming
JavaScript ProgrammingJavaScript Programming
JavaScript ProgrammingSehwan Noh
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an OverviewRoberto Casadei
 
Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Geeks Anonymes
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin XPeppers
 
Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022Simplilearn
 
Inheritance : Extending Classes
Inheritance : Extending ClassesInheritance : Extending Classes
Inheritance : Extending ClassesNilesh Dalvi
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate pptAneega
 
Regular expression in javascript
Regular expression in javascriptRegular expression in javascript
Regular expression in javascriptToan Nguyen
 

Was ist angesagt? (20)

C# Basics
C# BasicsC# Basics
C# Basics
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
Java 8 - CJ
Java 8 - CJJava 8 - CJ
Java 8 - CJ
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
JavaScript Programming
JavaScript ProgrammingJavaScript Programming
JavaScript Programming
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an Overview
 
Why rust?
Why rust?Why rust?
Why rust?
 
Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)Modern c++ (C++ 11/14)
Modern c++ (C++ 11/14)
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
Java I/o streams
Java I/o streamsJava I/o streams
Java I/o streams
 
Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022Kotlin InDepth Tutorial for beginners 2022
Kotlin InDepth Tutorial for beginners 2022
 
Inheritance : Extending Classes
Inheritance : Extending ClassesInheritance : Extending Classes
Inheritance : Extending Classes
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate ppt
 
C++ oop
C++ oopC++ oop
C++ oop
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Regular expression in javascript
Regular expression in javascriptRegular expression in javascript
Regular expression in javascript
 
Functions in C++
Functions in C++Functions in C++
Functions in C++
 

Ähnlich wie Kotlin as a Better Java

Kotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrainsKotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrainsJigar Gosar
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607Kevin Hazzard
 
Python programming: Anonymous functions, String operations
Python programming: Anonymous functions, String operationsPython programming: Anonymous functions, String operations
Python programming: Anonymous functions, String operationsMegha V
 
Pydiomatic
PydiomaticPydiomatic
Pydiomaticrik0
 
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]Chris Adamson
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, SwiftYandex
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingGarth Gilmour
 
Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Mohamed Nabil, MSc.
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Codemotion
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in goYusuke Kita
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaDaniel Sebban
 
Kotlin 101 for Java Developers
Kotlin 101 for Java DevelopersKotlin 101 for Java Developers
Kotlin 101 for Java DevelopersChristoph Pickl
 
Kotlin Austin Droids April 14 2016
Kotlin Austin Droids April 14 2016Kotlin Austin Droids April 14 2016
Kotlin Austin Droids April 14 2016DesertJames
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 

Ähnlich wie Kotlin as a Better Java (20)

Kotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrainsKotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrains
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 
Functions
FunctionsFunctions
Functions
 
C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607C# 6 and 7 and Futures 20180607
C# 6 and 7 and Futures 20180607
 
Python programming: Anonymous functions, String operations
Python programming: Anonymous functions, String operationsPython programming: Anonymous functions, String operations
Python programming: Anonymous functions, String operations
 
Pydiomatic
PydiomaticPydiomatic
Pydiomatic
 
Python idiomatico
Python idiomaticoPython idiomatico
Python idiomatico
 
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
Oh Crap, I Forgot (Or Never Learned) C! [CodeMash 2010]
 
Denis Lebedev, Swift
Denis  Lebedev, SwiftDenis  Lebedev, Swift
Denis Lebedev, Swift
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Kotlin for Android Developers - 3
Kotlin for Android Developers - 3
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in go
 
Python crush course
Python crush coursePython crush course
Python crush course
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with Scala
 
Python basic
Python basicPython basic
Python basic
 
Kotlin 101 for Java Developers
Kotlin 101 for Java DevelopersKotlin 101 for Java Developers
Kotlin 101 for Java Developers
 
Kotlin Austin Droids April 14 2016
Kotlin Austin Droids April 14 2016Kotlin Austin Droids April 14 2016
Kotlin Austin Droids April 14 2016
 
Effective Object Oriented Design in Cpp
Effective Object Oriented Design in CppEffective Object Oriented Design in Cpp
Effective Object Oriented Design in Cpp
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 

Mehr von Garth Gilmour

Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android UpdateGarth Gilmour
 
TypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSTypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSGarth Gilmour
 
Shut Up And Eat Your Veg
Shut Up And Eat Your VegShut Up And Eat Your Veg
Shut Up And Eat Your VegGarth Gilmour
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
A TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresA TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresGarth Gilmour
 
The Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITThe Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITGarth Gilmour
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScriptGarth Gilmour
 
Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Garth Gilmour
 
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
Using Kotlin, to Create Kotlin,to Teach Kotlin,in SpaceUsing Kotlin, to Create Kotlin,to Teach Kotlin,in Space
Using Kotlin, to Create Kotlin, to Teach Kotlin, in SpaceGarth Gilmour
 
Is Software Engineering A Profession?
Is Software Engineering A Profession?Is Software Engineering A Profession?
Is Software Engineering A Profession?Garth Gilmour
 
Social Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlySocial Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlyGarth Gilmour
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala MakeoverGarth Gilmour
 
Transitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinTransitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinGarth Gilmour
 
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Garth Gilmour
 
The Three Horse Race
The Three Horse RaceThe Three Horse Race
The Three Horse RaceGarth Gilmour
 
The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming Garth Gilmour
 
BelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopBelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopGarth Gilmour
 
Kotlin The Whole Damn Family
Kotlin The Whole Damn FamilyKotlin The Whole Damn Family
Kotlin The Whole Damn FamilyGarth Gilmour
 

Mehr von Garth Gilmour (20)

Compose in Theory
Compose in TheoryCompose in Theory
Compose in Theory
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
 
TypeScript Vs. KotlinJS
TypeScript Vs. KotlinJSTypeScript Vs. KotlinJS
TypeScript Vs. KotlinJS
 
Shut Up And Eat Your Veg
Shut Up And Eat Your VegShut Up And Eat Your Veg
Shut Up And Eat Your Veg
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
A TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS AdventuresA TypeScript Fans KotlinJS Adventures
A TypeScript Fans KotlinJS Adventures
 
The Heat Death Of Enterprise IT
The Heat Death Of Enterprise ITThe Heat Death Of Enterprise IT
The Heat Death Of Enterprise IT
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)Generics On The JVM (What you don't know will hurt you)
Generics On The JVM (What you don't know will hurt you)
 
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
Using Kotlin, to Create Kotlin,to Teach Kotlin,in SpaceUsing Kotlin, to Create Kotlin,to Teach Kotlin,in Space
Using Kotlin, to Create Kotlin, to Teach Kotlin, in Space
 
Is Software Engineering A Profession?
Is Software Engineering A Profession?Is Software Engineering A Profession?
Is Software Engineering A Profession?
 
Social Distancing is not Behaving Distantly
Social Distancing is not Behaving DistantlySocial Distancing is not Behaving Distantly
Social Distancing is not Behaving Distantly
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
 
Transitioning Android Teams Into Kotlin
Transitioning Android Teams Into KotlinTransitioning Android Teams Into Kotlin
Transitioning Android Teams Into Kotlin
 
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
Simpler and Safer Java Types (via the Vavr and Lambda Libraries)
 
The Three Horse Race
The Three Horse RaceThe Three Horse Race
The Three Horse Race
 
The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming The Bestiary of Pure Functional Programming
The Bestiary of Pure Functional Programming
 
BelTech 2019 Presenters Workshop
BelTech 2019 Presenters WorkshopBelTech 2019 Presenters Workshop
BelTech 2019 Presenters Workshop
 
Kotlin The Whole Damn Family
Kotlin The Whole Damn FamilyKotlin The Whole Damn Family
Kotlin The Whole Damn Family
 

Kürzlich hochgeladen

Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 

Kürzlich hochgeladen (20)

Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 

Kotlin as a Better Java

  • 1. © Instil Software 2017 September 2017 eamonn.boyle@instil.coeamonn.boyle@instil.cogarth.gilmour@instil.co | eamonn.boyle@instil.co Kotlin as a Better Java Cork Functional Programmers and Cork Java Users Group
  • 2. © Instil Software 2017 C C++ Java C# Pascal Delphi Basic Visual Basic VB .NET Perl F# Java Script CoffeeScript 1990 2000 2010 TypeScript Jython JRuby PowerShell Dart Scala Clojure Kotlin Groovy Go Objective C Shell Scripting Swift Python Ruby
  • 3. © Instil Software 2017 Scala Kotlin Swift
  • 4. © Instil Software 2017 TypeScript
  • 5. © Instil Software 2017 The New Era of Programming Pt1 Everything is an object Type inference Functions • Can be free • Can be nested • Can be single expression • Can be lambdas • Can be referenced • Don’t return null • Use lambda syntax for inputs and outputs
  • 6. © Instil Software 2017 The New Era of Programming Pt2 String interpolation No field declarations • Primary constructors • Auto-properties Collections • Are unified • Are really generic • Include Tuples • Include Ranges • Support FP operations
  • 7. © Instil Software 2017 2010: Work begins on Kotlin within JetBrains 2011: First public announcement on Kotlin 2012: Open sourced under Apache 2 license 2016: Version one released 2017: First class support on Android A Kotlin Timeline
  • 8. © Instil Software 2017 Kotlin On Other Platforms JVM Bytecode Kotlin (JS) Kotlin (Native) Kotlin (JVM) Browser Interpreter Runtime OS
  • 9. © Instil Software 2017 A Simple Case Study
  • 10. © Instil Software 2017 Enter some numbers or three 'X' to finish 10 20 30 40 50 XXX Total of numbers is: 150 Enter some numbers or three 'X' to finish wibble Ignoring wibble 12 13 14 XXX Total of numbers is: 39 Enter some numbers or three 'X' to finish XXX Total of numbers is: 0
  • 11. © Instil Software 2017 public class Program { public static void main(String[] args) { @SuppressWarnings("resource") Scanner scanner = new Scanner(System.in); List<Integer> numbers = new ArrayList<>(); System.out.println("Enter some numbers or three 'X' to finish"); Pattern endOfInput = Pattern.compile("[X]{3}"); while(scanner.hasNextLine()) { if(scanner.hasNextInt()) { numbers.add(scanner.nextInt()); } else { if(scanner.hasNext(endOfInput)) { break; } else { String mysteryText = scanner.nextLine(); System.out.printf(“Ignoring %sn", mysteryText); } } } int total = numbers.stream().reduce((a,b) -> a + b).orElse(17); System.out.printf("Total of numbers is: %sn",total); } } java.demos.hello A Sample Java Program
  • 12. © Instil Software 2017 fun main(args: Array<String>) { val numbers = mutableListOf<Int>() val scanner = Scanner(System.`in`) val endOfInput = Regex("[X]{3}") println("Enter some numbers or three 'X' to finish") while (scanner.hasNextLine()) { if (scanner.hasNextInt()) { numbers += scanner.nextInt() } else { if (scanner.hasNext(endOfInput.toPattern())) { break } else { val mysteryText = scanner.nextLine() println("Ignoring $mysteryText") } } } //simpler alternative is ‘numbers.sum()’ val total = numbers.fold(0,Int::plus) println("Total of numbers is: $total") } kotlin.demos.hello The Sample Re-Written in Kotlin Points to note:  No redundant class  No semi-colons  Type inference  Both ‘val’ and ‘var’  Helper functions  String interpolation  Simplified collections  Interop with Java types  Simpler use of FP
  • 13. © Instil Software 2017 object NumbersDemo { def main(args: Array[String]) { var numbers = List[Int]() val scanner = new Scanner(System.in) val endOfInput = "[X]{3}".r println("Enter some numbers or three 'X' to finish") var notDone = true while (scanner.hasNextLine() && notDone) { if (scanner.hasNextInt()) { numbers = scanner.nextInt() :: numbers } else { if (scanner.hasNext(endOfInput.pattern)) { notDone = false } else { val mysteryText = scanner.nextLine() println(s"Ignoring $mysteryText") } } } //show support for FP val total1 = numbers.fold(0)(_ + _) println(s"Total of numbers is: $total1") //show simpler alternative in this case val total2 = numbers.sum println(s"Total of numbers is: $total2") } } demos.scala The Sample Rewritten in Scala
  • 14. © Instil Software 2017 Feature Java 9 Kotlin Scala Type Inference No Yes Yes Unified Type System No Yes Yes Protection from Null Results No Yes Yes String Interpolation No Yes Yes Extension Functions No Yes Partially Inline Functions No Yes Yes Primary Constructors No Yes Yes Case / Data Classes No Yes Yes Function Literals Yes Yes Yes Local Functions No Yes Yes Enclosure of local variables Partially Yes Yes Single Expression Functions No Yes Yes Tuples No Partially Yes Monads No Partially Yes Kotlin vs. Scala Comparison
  • 15. © Instil Software 2017 Type Inference
  • 16. © Instil Software 2017 class Person(val name: String) fun main(args: Array<String>) { val a = 123 val b = "ABC" val c = "[A-Z]{3}".toRegex() val d = 1..10 val e = Person("Jason") val f = arrayOf(a, b, c, d, e) f.forEach { println(it.javaClass.name) } } java.lang.Integer java.lang.String kotlin.text.Regex kotlin.ranges.IntRange basics.type.inference.Person basics.type.inference.Program Type Inference In Kotlin
  • 17. © Instil Software 2017 Managing Null Pointers
  • 18. © Instil Software 2017 A design goal for Kotlin was to minimise null pointer errors • They cant be eliminated without affecting interoperability The Kotlin compiler checks for nulls automatically • It is not possible for a regular variable to be set to null Every type you create has a nullable alternative • Written as ‘String?’ for ‘String’ and ‘Person?’ for ‘Person’ etc… • You can explicitly specify this but often it is inferred Nullable types often occur in function signatures • So ‘fun foo() Int’ cannot return null but ‘fun foo() Int?’ can Managing Null Pointers in Kotlin
  • 19. © Instil Software 2017 The ‘?.’ syntax makes a call only if the reference is not null • So ‘foo?.bar()’ would only call ‘bar’ if ‘foo’ was not null • Calls can be chained as required e.g. ‘foo?.bar().zed()’ The ‘?:’ syntax is used to specify a backup value • So ‘foo()?: “bar”’ returns ‘bar’ if the LHS is null • Note the RHS is only evaluated if required The ‘!!.’ syntax is for when you want an exception • For example when replacing a Java library with Kotlin whilst preserving exactly the same behaviour • So ‘foo||.bar()’ throws an exception if ‘foo’ is null • The garishness of the operator makes it easy to spot during pair programming and/or code reviews Operators for Nullable Types
  • 20. © Instil Software 2017 fun foo(input: Int) = if(input > 0) "abc" else "def" //return type is String fun bar(input: Int) = if(input > 0) "abc" else null //return type is String? fun main(args: Array<String>) { val str1 = foo(12) //inferred type is String val str2 = bar(34) //inferred type is String? val str3: String = foo(12) //declared type is String val str4: String? = bar(34) //declared type must be String? println(bar(12)?.toUpperCase()) //safe call operator (success) println(bar(-12)?.toUpperCase()) //safe call operator (failure) println(bar(12)?: "wibble") //elvis operator (success) println(bar(-12)?: "wibble") //elvis operator (failure) println(bar(12)!!.toUpperCase()) //NPE operator (success) try { println(bar(-12)!!.toUpperCase()) //NPE operator (failure) } catch(ex: Throwable) { println("Finally a NPE :-)") } } basics.safety.Program Managing Null Pointers in Kotlin ABC null abc wibble ABC Finally a NPE :-)
  • 21. © Instil Software 2017 fun demo1(input: Int) { println("Demo1 called with $input") } fun demo2(input: Int): Unit { //same as above println("Demo2 called with $input") } fun demo3(input: Int): String = "Demo3 called with $input" fun demo4(input: Int): String { return "Demo4 called with $input" } fun demo5(input: Int = 456): String { return "Demo5 called with $input" } fun demo6(vararg input:Int) = input.reduce { a,b -> a + b} fun demo7(port: Int, timeout:Int, retries: Int): String { return “““Trying to connect on port $port with $retries retries and a timeout of $timeout ””” } basics.functions.Program.kt Function Declarations
  • 22. © Instil Software 2017 fun main(args: Array<String>) { demo1(123) demo2(123) println(demo3(123)) println(demo4(123)) println(demo5(123)) println(demo5()) println("Adding numbers gives: ${demo6(10,20,30,40,50)}") println(demo7(timeout = 60, port=8080, retries = 10)) } basics.functions.Program.kt Demo1 called with 123 Demo2 called with 123 Demo3 called with 123 Demo4 called with 123 Demo5 called with 123 Demo5 called with 456 Adding numbers gives: 150 Trying to connect on port 8080 with 10 retries and a timeout of 60 Function Declarations
  • 23. © Instil Software 2017 A Kotlin function can be declared as infix • This allows it to be used as if it were a keyword • E.g. ‘12 downTo 1’ is the same as ‘12.downTo(1)’ • An infix function must follow some simple rules: • It can only take a single parameter • It must be a member of a type (i.e. a method) • Or an extension to an existing type • It must be declared using the ‘infix’ keyword It is possibly to pass references to functions and anonymous functions (aka lambdas) as parameters Special Kinds Of Function
  • 24. © Instil Software 2017 class Number(val value: Int) { infix fun plus(input: Int): Number { return Number(value + input) } infix fun minus(input: Int): Number { return Number(value - input) } fun forEach(action: (Int) -> Unit) { for(x in 1..value) { action(x) } } } fun main(args: Array<String>) { val num1 = Number(5) val num2 = num1 plus 7 val num3 = num2 minus 3 num1.forEach { print("$it ")} println() num2.forEach { print("$it ")} println() num3.forEach { print("$it ")} } 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 basics.functions.infix Special Function Declarations
  • 25. © Instil Software 2017 Classes in Kotlin
  • 26. © Instil Software 2017 When coding in Kotlin we think in terms of properties • In Kotlin it isn’t possible to manually add fields to a class • Instead you add properties, which are public by default When you add a property to a class Kotlin will: • Declare a ‘backing field’ of the appropriate type • Declare a standard Java getter method • Unless the property has been declared private • Declare a standard Java setter method • Assuming the property has been declared with ‘var’ Accessor methods are automatically invoked for you • So ‘val wage = emp.salary’ is ‘val wage = emp.getSalary()’ • Similarly ‘emp.salary = n’ becomes ‘emp.setSalary(n)’ Classes and Properties in Kotlin
  • 27. © Instil Software 2017 class Person { var name: String = "Dave" fun sayHello() = println("Hello $name") } fun main(args: Array<String>) { val p = Person() println(p.name) p.sayHello() p.name = "Jane" println(p.name) p.sayHello() } oo.properties javap -p oo.properties.Person Compiled from "Person.kt" public final class oo.properties.Person { private java.lang.String name; public final java.lang.String getName(); public final void setName(java.lang.String); public final void sayHello(); public oo.properties.regular.Person(); } Classes and Properties in Kotlin Dave Hello Dave Jane Hello Jane Note Kotlin does not require ‘new’
  • 28. © Instil Software 2017 Classes and Properties in Kotlin $ javap -p -c oo.properties.regular.PersonKt Compiled from "Person.kt" public final class oo.properties.regular.PersonKt { public static final void main(java.lang.String[]); Code: 0: aload_0 1: ldc #9 // String args 3: invokestatic #15 // Method …/Intrinsics.checkParameterIsNotNull:(…)V 6: new #17 // class oo/properties/regular/Person 9: dup 10: invokespecial #21 // Method oo/properties/regular/Person."<init>":()V 13: astore_1 14: aload_1 15: invokevirtual #25 // Method oo/properties/regular/Person.getName:()Ljava/lang/String; 18: astore_2 19: getstatic #31 // Field java/lang/System.out:Ljava/io/PrintStream; 22: aload_2 23: invokevirtual #37 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 26: aload_1 27: invokevirtual #40 // Method oo/properties/regular/Person.sayHello:()V 30: aload_1 31: ldc #42 // String Jane 33: invokevirtual #46 // Method oo/properties/regular/Person.setName:(Ljava/lang/String;)V 36: aload_1 37: invokevirtual #25 // Method oo/properties/regular/Person.getName:()Ljava/lang/String; 40: astore_2 41: getstatic #31 // Field java/lang/System.out:Ljava/io/PrintStream; 44: aload_2 45: invokevirtual #37 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 48: aload_1 49: invokevirtual #40 // Method oo/properties/regular/Person.sayHello:()V 52: return }
  • 29. © Instil Software 2017 The default accessor methods can be overridden • By providing ‘get’ and/or ‘set’ blocks after the declaration • The backing field can be accessed via the keyword ‘field’ • Note this is only allowed within the ‘get/set’ blocks This is useful in two scenarios: • When you want to base a property on an expression • Such as the ‘empty’ property of a custom collection • When you want to add validation rules • E.g. the setter method for a ‘wage’ property could check if the new value was within the salary band of the employee Customising Properties
  • 30. © Instil Software 2017 fun main(args: Array<String>) { val p = Person() p.sayHello() p.name = "Jane" p.sayHello() } class Person { var name: String = "Dave" get() = "[$field]" set(value) { field = "$value Jones" } fun sayHello() = println("Hello $name") } oo.properties.customized Hello [Dave] Hello [Jane Jones] Customising Properties
  • 31. © Instil Software 2017 Kotlin provides a feature called ‘primary constructors’ • Also available in Scala and TypeScript and coming in C# The class and constructor declarations are merged • Removing the need to retype the class name, introduce extra braces and both declare and initialize fields manually The way the parameters are declared is crucial • If declared without ‘var’ or ‘val’ they are normal inputs • No extra members will be added to the class • If declared with var / val then fields and properties are added • When ‘val’ is used only a getter method is created The properties will be public by default • You can alter this by adding an access modifier Kotlin and Primary Constructors
  • 32. © Instil Software 2017 package oo.basics class Person(name: String, age: Int) oo.basics javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors Here the parameters lack ‘val’ or ‘var’ so no fields or properties are created.
  • 33. © Instil Software 2017 package oo.basics class Person(val name: String, val age: Int) oo.basics $ javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String name; private final int age; public final java.lang.String getName(); public final int getAge(); public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors Adding ‘val’ to the parameters means that a backing field will be created, initialised and accessible via a ‘getter’ method
  • 34. © Instil Software 2017 package oo.basics class Person(var name: String, var age: Int) oo.basics Compiled from "Person.kt” public final class oo.basics.Person { private java.lang.String name; private int age; public final java.lang.String getName(); public final void setName(java.lang.String); public final int getAge(); public final void setAge(int); public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors Using ‘var’ instead of ‘val’ means that the compiler also generates ‘setter’ methods
  • 35. © Instil Software 2017 package oo.basics class Person(val name: String, var age: Int) oo.basics $ javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String name; private int age; public final java.lang.String getName(); public final int getAge(); public final void setAge(int); public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors There is no issue with using both ‘val’ and ‘var’ on different parameters. Note the default access is public.
  • 36. © Instil Software 2017 package oo.basics class Person(public val name: String, protected var age: Int) oo.basics $ javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String name; private int age; public final java.lang.String getName(); protected final int getAge(); protected final void setAge(int); public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors Adding ‘public’ to the ‘name’ field will have no effect as that is the default. Adding ‘protected’ to ‘age’ will change the access level of the methods but we would need to declare the class ‘open’ for this to be useful
  • 37. © Instil Software 2017 package oo.basics class Person(public val name: String, private var age: Int) oo.basics javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String name; private int age; public final java.lang.String getName(); public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors Declaring a parameter as private causes the backing field to be created but not the accessor methods.
  • 38. © Instil Software 2017 package oo.basics class Person(private val name: String, private var age: Int) oo.basics $ javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String name; private int age; public oo.basics.Person(java.lang.String, int); } Understanding Primary Constructors There is no issue with all the parameters being private
  • 39. © Instil Software 2017 package oo.basics class Person(val name: String, val age: Int) { private val address = "10 Arcatia Road" init { println("Person object created") } } oo.basics javap -p -c oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private final java.lang.String address; private final java.lang.String name; private final int age; public final java.lang.String getName(); public final int getAge(); public oo.basics.Person(java.lang.String, int); --------- Earlier code omitted --------- 21: ldc #8 // String 10 Arcatia Road 23: putfield #36 // Field address:Ljava/lang/String; 26: ldc #38 // String Person object created 28: astore_3 29: getstatic #44 // Field java/lang/System.out:Ljava/io/PrintStream; 32: aload_3 33: invokevirtual #50 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 36: return } Understanding Primary Constructors
  • 40. © Instil Software 2017 package oo.basics class Person(val name: String, val age: Int) { private var address = "10 Arcatia Road" init { println("Person object created") } constructor(name: String, age: Int, address: String) : this(name,age) { println("Secondary constructor called") this.address = address; } } oo.secondary.constructors $ javap -p oo.basics.Person Compiled from "Person.kt" public final class oo.basics.Person { private java.lang.String address; private final java.lang.String name; private final int age; public final java.lang.String getName(); public final int getAge(); public oo.basics.Person(java.lang.String, int); public oo.basics.Person(java.lang.String, int, java.lang.String); } Adding Secondary Constructors
  • 41. © Instil Software 2017 Kotlin adds the following to data classes: • The familiar ‘equals’ and ‘hashCode’ methods • A straightforward implementation of ‘toString’ • Which returns output of type ‘Foo(bar=123, zed=“abc”)’ • A ‘copy’ method which returns a clone of the object • Component methods for destructuring (see later) The ‘copy’ method allows you to make changes • By default the properties of the copy are set to the same values as the original, but you can alter them if you like • E.g. ‘val person2 = person1.copy(age=28)’ Declaring Data Classes
  • 42. © Instil Software 2017 fun main(args: Array<String>) { val emp1 = Employee("Dave Jones", "10 Arcatia Road", 30000.0) val emp2 = Employee("Dave Jones", "10 Arcatia Road", 30000.0) println(emp1) println(emp2) println(emp1 === emp2) println(emp1 == emp2) println(emp1.equals(emp2)) println(emp1.hashCode()) println(emp2.hashCode()) val emp3 = emp2.copy(salary = 40000.0) println(emp3) } data class Employee(val name: String, val address: String, val salary: Double) oo.entities Declaring Data Classes Employee(name=Dave Jones, address=10 Arcatia Road, salary=30000.0) Employee(name=Dave Jones, address=10 Arcatia Road, salary=30000.0) false true true 1296289951 Employee(name=Dave Jones, address=10 Arcatia Road, salary=40000.0) 1296289951
  • 43. © Instil Software 2017 Generics
  • 44. © Instil Software 2017 Generics in Kotlin fun thoughtExperiment() { val myList = LinkedList<Manager>() foobar(myList) //should this be allowed? } fun foobar(input: LinkedList<Employee>) { input.add(Employee(“Dave”)) }
  • 45. © Instil Software 2017 We can simplify our problem by restricting the generic type • A read-only list would solve the current problem • We could pass in a list of any subtype of ‘Employee’ • Since the methods of the list could not accept instances of ‘T’ there would be no danger of adding the wrong type • A write-only list might be useful as well • ‘fun foobar(input: WriteOnlyList<Manager>)’ could be called with a write-only list of ‘Employee’ or ‘Person’ • Since ‘input.add(Manager(“Jane”))’ works in all cases • Assuming that Manager  Employee  Person Generics in Kotlin
  • 46. © Instil Software 2017 Kotlin allows you to restrict generic types in this way • Saying ‘out T’ means that ‘T’ objects can only be returned • Saying ‘in T’ means that ‘T’ object can only be accepted • This is referred to as ‘Declaration Site Type Variance’ Generics in Kotlin
  • 47. © Instil Software 2017 open class Employee open class Manager : Employee() open class Director : Manager() class ReadWriteList<T> { fun get(index: Int) : T? = null fun findFirst(p: (T) -> Boolean) : T? = null fun findAll(p: (T) -> Boolean) : ReadWriteList<T>? = null fun add(item: T) {} fun add(index: Int, item: T) {} fun addAll(items: ReadWriteList<T>) {} } class ReadOnlyList<out T> { fun get(index: Int) : T? = null fun findFirst(p: (T) -> Boolean) : T? = null fun findAll(p: (T) -> Boolean) : ReadOnlyList<T>? = null } class WriteOnlyList<in T> { fun add(item: T) {} fun add(index: Int, item: T) {} fun addAll(vararg items: T) {} } generics.declaration.site.variance.Program.kt Generics in Kotlin
  • 48. © Instil Software 2017 fun demo1(input: ReadWriteList<Manager>) { input.add(Manager()) //this is not controversial input.add(Director()) //this surprises most people } fun demo2(input: ReadOnlyList<Manager>) { //can only access items here } fun demo3(input: WriteOnlyList<Manager>) { //can only insert items here } fun main(args: Array<String>) { //demo1(ReadWriteList<Employee>()) //will not compile demo1(ReadWriteList<Manager>()) //demo1(ReadWriteList<Director>()) //will not compile //demo2(ReadOnlyList<Employee>()) //will not compile demo2(ReadOnlyList<Manager>()) demo2(ReadOnlyList<Director>()) demo3(WriteOnlyList<Employee>()) demo3(WriteOnlyList<Manager>()) //demo3(WriteOnlyList<Director>()) //will not compile } generics.declaration.site.variance.Program.kt Generics in Kotlin
  • 49. © Instil Software 2017 When we say ‘class Foo<out T>’ then: • A function which takes a ‘Foo<Manager>’ will also accept a ‘Foo<Director>’ or any other subtype (such as ‘Foo<CTO>’) • Hence the possible set of valid values is infinite • This is because ‘Foo’ is acting as a producer and a reference of type Manager can refer to any instance of any subtype • We say that in this case ‘T’ is covariant When we say ‘class Foo<in T>’ then: • A function which takes a ‘Foo<Manager>’ will also accept either a ‘Foo<Employee>’ or a ‘Foo<Any>’ • This time the set of valid values is fixed • This is because ‘Foo’ acts as a consumer and an input of ‘Manager’ can be stored via a ref of ‘Employee’ or ‘Any’ • We say that in this case ‘T’ is contravariant Understanding Declaration Site Variance
  • 50. © Instil Software 2017 Declaration site variance is not always sufficient • Consider a function which takes two lists of type ‘Employee’ and where we want to transfer items between the lists • The compiler needs to be able to check, on a call by call basis, whether the operations we intend to perform are safe • E.g. it could be called in one place with lists of ‘Employee’ and ‘Manager’ and in another with ‘CTO’ and ‘Director’ We simplify the compilers job by using the ‘in’ and ‘out’ modifiers directly on the parameters to the function • E.g. fun demo(p1: MyList<out Thing>, p2: MyList<in Thing>) • This allows the compiler to validate the code in the function and determine whether a given call should be permitted • It is known as ‘use-site variance’ or ‘type projection’ Understanding Use Site Variance
  • 51. © Instil Software 2017 fun copyFirstTen(input: ReadWriteList<out Employee>, output: ReadWriteList<in Employee>) { //try to copy first 10 items for(x in 0..9) { val item = input.get(x) if(item != null) { output.add(item) } } } fun main(args: Array<String>) { val tst1 = ReadWriteList<Employee>() val tst2 = ReadWriteList<Manager>() val tst3 = ReadWriteList<Director>() copyFirstTen(tst1,tst1) //fine copyFirstTen(tst2,tst1) //fine copyFirstTen(tst3,tst1) //fine //copyFirstTen(tst1,tst2) //will not compile //copyFirstTen(tst1,tst3) //will not compile } generics.use.site.variance.Program.kt Generics in Kotlin
  • 52. © Instil Software 2017 So far we have assumed our code can be fully generified • We can rewrite our ‘LinkedList’ of string as ‘LinkedList<T>’ and it will then automatically work for all possible values of ‘T’ This is (mostly) true of collections but false in other cases • Often we find code which can only be partially generified • For example it might only work for any type which has a ‘compareTo’ method, or which implements ‘Iterable’ Generic Constraints allow us to state this in code • For example the function ‘fun <T: Iterable> foobar(p: T)’ can be invoked with any type which implements ‘Iterable’ • As in Java this is referred to as an ‘upper bound’ Generic Constraints in Kotlin
  • 53. © Instil Software 2017 open class Employee { fun work() {} } open class Manager : Employee() { fun manage() {} } open class Director : Manager() { fun direct() {} } fun <T> demo1(input: T) { println(input.toString()) } fun <T : Employee> demo2(input: T) { input.work() } fun <T : Manager> demo3(input: T) { input.work() input.manage() } fun <T : Director> demo4(input: T) { input.work() input.manage() input.direct() } generics.constraints.Program Generic Constraints
  • 54. © Instil Software 2017 fun main(args: Array<String>) { demo1(Employee()) demo1(Manager()) demo1(Director()) demo2(Employee()) demo2(Manager()) demo2(Director()) //demo3(Employee()) // Will not compile demo3(Manager()) demo3(Director()) //demo4(Employee()) // Will not compile //demo4(Manager()) // Will not compile demo4(Director()) } generics.constraints.Program Generic Constraints
  • 55. © Instil Software 2017 It is possible to specify multiple generic constraints • Useful when a type needs to implement multiple interfaces • E.g. a type might need to be both serializable and cloneable Multiple constraints use a different syntax • The function declaration ends in a ‘where’ clause, whose value is a series of constraints on the type parameter(s) Generic Constraints in Kotlin
  • 56. © Instil Software 2017 interface Edible { fun eat() } interface Drinkable { fun drink() } class Pie : Edible { override fun eat() {} } class Ale : Drinkable { override fun drink() {} } class Ramen : Edible, Drinkable { override fun eat() {} override fun drink() {} } demos.constraints.generics.multiple.Program Generic Constraints in Kotlin
  • 57. © Instil Software 2017 fun <T> demo(input: T) where T: Edible, T: Drinkable { input.eat() input.drink() } fun main(args: Array<String>) { //demo(Pie()) // Will not compile //demo(Ale()) // Will not compile demo(Ramen()) } demos.constraints.generics.multiple.Program Generic Constraints in Kotlin
  • 58. © Instil Software 2017 Collections
  • 59. © Instil Software 2017 Kotlin provides data structures via ‘kotlin.collections’ • As in Java, arrays are not part of the collections library • Support for arrays is provided in the core ‘kotlin’ package Collections are typically created indirectly • Via methods such as ‘emptyList’ and ‘listOf’ Both mutable and immutable collections are provided • ‘listOf’ provides a list where adding returns a new collection • ‘mutableListOf’ provides a list whose state can be changed At present everything is implemented via JSE collections • So you are given a read-only view of a mutable collection Collections in Kotlin
  • 60. © Instil Software 2017 fun printList(input: List<Int>) { println("This is a list of type ${input.javaClass.name}") if(input.isEmpty()) { println("tThe list is empty") } else { val content = input.fold(""){a,b -> a + b + " "} println("tThe list holds: $content") } } fun main(args: Array<String>) { val list1: List<Int> = emptyList() val list2 = emptyList<Int>() val list3 = listOf(12) val list4 = listOf(12,34,56) val list5 = mutableListOf(12,34,56) printList(list1) printList(list2) printList(list3) printList(list4) printList(list5) collections.basic.Program Introducing Kotlin Collections
  • 61. © Instil Software 2017 val list6 = list4.plus(78) list5.add(78) println("-------------") printList(list4) printList(list5) printList(list6) } collections.basic.Program This is a list of type kotlin.collections.EmptyList The list is empty This is a list of type kotlin.collections.EmptyList The list is empty This is a list of type java.util.Collections$SingletonList The list holds: 12 This is a list of type java.util.Arrays$ArrayList The list holds: 12 34 56 This is a list of type java.util.ArrayList The list holds: 12 34 56 ------------- This is a list of type java.util.Arrays$ArrayList The list holds: 12 34 56 This is a list of type java.util.ArrayList The list holds: 12 34 56 78 This is a list of type java.util.ArrayList The list holds: 12 34 56 78 Introducing Kotlin Collections List 4 was not modified by the call to ‘plus’
  • 62. © Instil Software 2017 Example Types from the Collections Hierarchy Iterable Collection MutableCollectionList MutableList AbstractMutableList ArrayList RandomAcces s java.util.AbstractList listOf emptyList arrayListOf mutableListOf
  • 63. © Instil Software 2017 fun main(args: Array<String>) { val myList = listOf("ab","cd","ef") println(myList.elementAtOrElse(0, {"Nothing at $it"})) println(myList.elementAtOrElse(3, {"Nothing at $it"})) val sb = StringBuilder() myList.joinTo(buffer = sb,separator = " ", prefix=">>", postfix="<<") println(sb) val myList2 = myList.reversed() println(myList2) } collections.functions.Program ab Nothing at 3 >>ab cd ef<< [ef, cd, ab] Accessing Values in Collections
  • 64. © Instil Software 2017 Kotlin provides support for destructuring • I.e. retrieving multiple values from a collection at once • This is often found in scripting languages but rare elsewhere The syntax is ‘val (a,b,c) = myThing’ • If ‘myThing’ is a list this will be compiled as calls to ‘get’ • Otherwise the compiler will expect there to be methods of the form ‘componentN’ and create declarations as below Destructuring in Collections val a = myList.component1() val b = myList.component2() val c = myList.component3()
  • 65. © Instil Software 2017 fun main(args: Array<String>) { var myList = listOf(12,34,56) var myPair = Pair(12,"ab") var (a,b,c) = myList var (d,e) = myPair println("List values are ${a}, ${b} and ${c}") println("Pair values are ${d} and ${e}") } collections.destructuring.Program List values are 12, 34 and 56 Pair values are 12 and ab Destructuring in Collections
  • 66. © Instil Software 2017 Destructing In Collections javap -p -c collections.destructuring.ProgramKt Compiled from "Program.kt" public final class collections.destructuring.ProgramKt { public static final void main(java.lang.String[]); Code: 63: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 68: checkcast #43 // class java/lang/Number 71: invokevirtual #47 // Method java/lang/Number.intValue:()I 82: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 87: checkcast #43 // class java/lang/Number 90: invokevirtual #47 // Method java/lang/Number.intValue:()I 102: invokeinterface #41, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 107: checkcast #43 // class java/lang/Number 110: invokevirtual #47 // Method java/lang/Number.intValue:()I 123: invokevirtual #51 // Method kotlin/Pair.component1:()Ljava/lang/Object; 126: checkcast #43 // class java/lang/Number 129: invokevirtual #47 // Method java/lang/Number.intValue:()I 136: invokevirtual #54 // Method kotlin/Pair.component2:()Ljava/lang/Object; 139: checkcast #56 // class java/lang/String Calls to ‘get’ method Calls to ‘componentN’ methods
  • 67. © Instil Software 2017 Functional Programming
  • 68. © Instil Software 2017 The ‘map’ function converts a list of ‘T’ to a list of ‘U’ • Based on a mapping function that you provide The ‘filter’ function produces a smaller list • Based on a predicate function that you provide The ‘partition’ function is similar to filter • But it sorts the items into two separate lists based on the test The ‘Functional Toolkit’ fun <T,U>map(input: List<T>, mappingFunc: (T)->U): List<U> { … } fun <T>filter(input: List<T>, filterFunc: (T)->Boolean): List<T> { … } fun <T>partition(input: List<T>, filterFunc: (T)->Boolean): Pair<List<T>,List<T>> {
  • 69. © Instil Software 2017 fun <T,U>map(input: List<T>, mappingFunc: (T)->U): List<U> { val results = ArrayList<U>() for(item in input) { results.add(mappingFunc(item)); } return results } fun <T>filter(input: List<T>, filterFunc: (T)->Boolean): List<T> { val results = ArrayList<T>() for(item in input) { if(filterFunc(item)) { results.add(item); } } return results } fun <T>partition(input: List<T>, filterFunc: (T)->Boolean): Pair<List<T>,List<T>> { val results = Pair(ArrayList<T>(),ArrayList<T>()) for(item in input) { if(filterFunc(item)) { results.first.add(item); } else { results.second.add(item); } } return results } coding.the.functional.toolkit Implementing the ‘Functional Toolkit’ By Hand
  • 70. © Instil Software 2017 fun main(args: Array<String>) { val originalData = arrayListOf<String>("12","34","56","78","90") val mappedData = map(originalData, String::toInt) val filteredData = filter(mappedData) { it > 50 } val partitionedData = partition(mappedData) { it > 50 } printResults("Results of mapping",mappedData) printResults("Results of filtering", filteredData) printResults("Results of partitioning", partitionedData) } fun<T> printResults(title: String, input: List<T>) { println("----- $title -----") for(item in input) { println("t$item") } } fun<T,U> printResults(title: String, input: Pair<List<T>,List<U>>) { println("----- $title -----") println("tfirst items in pair") for(item in input.first) { println("tt$item") } println("tsecond items in pair") for(item in input.second) { println("tt$item") } } coding.the.functional.toolkit Implementing the ‘Functional Toolkit’ By Hand
  • 71. © Instil Software 2017 Implementing the ‘Functional Toolkit’ By Hand ----- Results of mapping ----- 12 34 56 78 90 ----- Results of filtering ----- 56 78 90 ----- Results of partitioning ----- first items in pair 56 78 90 second items in pair 12 34
  • 72. © Instil Software 2017 Higher level functions can also return new functions • Functional coders never implement a ‘family’ of functions • Instead they create a function that returns the one they currently need, plus as many variants as required A simple example is wrapping text in HTML tags • We could define one wrapper function per tag • This would be tedious and require periodic updates • We could write a function that took the tag name • But this would be ‘stringly typed code’ and prone to typos • We could write a function that takes a tag name and returns a function that takes arbitrary text and wraps it in the tag • This prevents us having to build and maintain a library of trivial functions whilst also protecting against simple errors Using Functions as Outputs
  • 73. © Instil Software 2017 fun wrapInH1(input: String) = "<h1>$input</h1>" fun wrapInH2(input: String) = "<h2>$input</h2>" fun wrapInTag(tagName: String, input: String): String { val openingTag = "<$tagName>" val closingTag = "</$tagName>" return "$openingTag$input$closingTag" } fun buildWrapper(tagName: String): (String) -> String { val openingTag = "<$tagName>" val closingTag = "</$tagName>" return { "$openingTag$it$closingTag" } } functions.returning.functions Using Functions as Outputs
  • 74. © Instil Software 2017 fun main(args: Array<String>) { println(wrapInH1("Marge")) println(wrapInH2("Homer")) println(wrapInTag("h3","Liza")) println(wrapInTag("h4","Bart")) val wrapInBold = buildWrapper("b") val wrapInItalics = buildWrapper("i") val wrapInMark = buildWrapper("mark") println(wrapInBold("Maggie")) println(wrapInItalics("Snowball III")) println(wrapInMark("Santas Little Helper")) } functions.returning.functions <h1>Marge</h1> <h2>Homer</h2> <h3>Liza</h3> <h4>Bart</h4> <b>Maggie</b> <i>Snowball III</i> <mark>Santas Little Helper</mark> Using Functions as Outputs
  • 75. © Instil Software 2017 In the previous example we returned a function literal • This worked well but in more complex cases we will be returning functions that contain larger quantities of code Instead we can return a reference to a local function • Functional languages like Kotlin allow functions to be nested within one another and these local functions to be returned In the following example we create ‘buildMatcher’ which: • Takes a regular expression in string format as its input • Builds and returns a function that takes some text and returns all the matches for the regular expression as a list of strings Returning Local Functions
  • 76. © Instil Software 2017 import kotlin.text.Regex fun main(args: Array<String>) { val data = "abcDEFghiJKLmnpPQRstuVWXyz" val matcher1 = buildMatcher("[A-Z]{3}") val matcher2 = buildMatcher("[a-z]{2,3}") println("First matches are:") for(str in matcher1(data)) { println("t$str") } println("Second matches are:") for(str in matcher2(data)) { println("t$str") } } fun buildMatcher(pattern: String): (String) -> Sequence<String> { fun matcher(text: String): Sequence<String> { val regex = Regex(pattern) return regex.findAll(text) .map { it.value } } return ::matcher } returning.functions Returning Local Functions
  • 77. © Instil Software 2017 Returning Local Functions First matches are: DEF JKL PQR VWX Second matches are: abc ghi mnp stu yz
  • 78. © Instil Software 2017 Functional Collections
  • 79. © Instil Software 2017 Kotlin collections offer the standard ‘functional toolkit’ • A summary of these operations is provided below • Remember you can add your own via extensions In the following example we: • Create a list of course objects with associated instructors • Query the data in increasingly complex ways The Built In Functional Toolkit Operation Name Description all, any,name Perform a test using a predicate first, filter, find, last Locate elements based on a predicate map, flatMap Transform the elements in a collection fold, foldRight, reduce, reduceRight Build a single value based on the elements groupBy, associateBy Group the elements based on a key selector
  • 80. © Instil Software 2017 data class Course( val id: String, val title: String, val courseType: CourseType, val duration: Int, val instructors: List<Trainer>) data class Trainer( val name: String, val rate: Double, val skills : List<String>) enum class CourseType { BEGINNER, INTERMEDIATE, ADVANCED } functional.using.the.toolki t Using the Functional Toolkit
  • 81. © Instil Software 2017 fun buildData(): List<Course> { val dave = Trainer("Dave Jones", 500.0, arrayListOf("SQL","Perl","PHP")) val jane = Trainer("Jane Smith", 750.0, arrayListOf("SQL","Java","JEE")) val pete = Trainer("Pete Hughes", 1000.0, arrayListOf("Java", "JEE", "C#", "Scala")) val mary = Trainer("Mary Donaghy", 1250.0, arrayListOf("Java", "JEE", "C#", "C++")) return arrayListOf( Course("AB12","Intro to Scala",BEGINNER,4,arrayListOf(pete)), Course("CD34","JEE Web Development",INTERMEDIATE,3,arrayListOf(pete, mary, jane)), Course("EF56","Meta-Programming in Ruby",ADVANCED,2,arrayListOf()), Course("GH78","OO Design with UML",BEGINNER,3,arrayListOf(jane,pete,mary)), Course("IJ90","Database Access with JPA",INTERMEDIATE,3, arrayListOf(jane)), Course("KL12","Design Patterns in C#",ADVANCED,2, arrayListOf(pete,mary)), Course("MN34","Relational Database Design",BEGINNER,4, arrayListOf(jane, dave)), Course("OP56",”MySql Stored Procedures",INTERMEDIATE,1, arrayListOf(jane, dave)), Course("QR78",”Parallel Programming",ADVANCED,2, arrayListOf(pete,mary)), Course("ST90","C++ Programming for Beginners",BEGINNER,5,arrayListOf(mary)), Course("UV12","UNIX Threading with PThreads",INTERMEDIATE,2,arrayListOf()), Course("WX34","Writing Linux Device Drivers",ADVANCED,3,arrayListOf(mary))) } functional.using.the.toolki t Using the Functional Toolkit
  • 82. © Instil Software 2017 fun main(args: Array<String>) { val data = buildData() titlesOfCourses(data) titlesOfCoursesWithoutATrainer(data) namesAndRatesOfTrainers(data) theNumberOfAdvancedCourses(data) totalDurationsOfBeginnerAndNonBeginnerCourses(data) everyPairOfTrainersThatCouldDeliverJava(data) possibleCostsOfJeeWebDevelopment(data) coursesIdsAndTitlesGroupedByType(data) } functional.using.the.toolki t Using the Functional Toolkit
  • 83. © Instil Software 2017 fun printTabbed(input: Any) = println("t$input") fun printTitle(title: String) = println(title) fun printLine() = println("--------") //An extension function to return pairs of items without duplicates // note this is the simplest possible implementation fun List<String>.combinations(): List<Pair<String,String>> { val results = ArrayList<Pair<String,String>>() for(str1 in this) { for(str2 in this) { if(!str1.equals(str2)) { if(!results.contains(Pair(str2,str1))) { results.add(Pair(str1, str2)) } } } } return results } functional.using.the.toolki t Using the Functional Toolkit
  • 84. © Instil Software 2017 fun titlesOfCourses(courses: List<Course>) { printTitle("Titles of courses:") courses.map { it.title } .forEach(::printTabbed) printLine() } fun titlesOfCoursesWithoutATrainer(courses: List<Course>) { printTitle("Titles of courses without a trainer:") courses.filter { it.instructors.isEmpty() } .map { it.title } .forEach(::printTabbed) printLine() } fun namesAndRatesOfTrainers(courses: List<Course>) { printTitle("Names and rates of trainers:") courses.flatMap { it.instructors } .toSet() .map { Pair(it.name,it.rate)} .forEach(::printTabbed) printLine() } functional.using.the.toolkit Using the Functional Toolkit
  • 85. © Instil Software 2017 fun theNumberOfAdvancedCourses(courses: List<Course>) { printTitle("The number of advanced courses:") printTabbed(courses.count {it.courseType == ADVANCED}) printLine() } fun totalDurationsOfBeginnerAndNonBeginnerCourses(courses: List<Course>) { printTitle("Total days for both beginner and non-beginner courses") val splitCourses = courses.partition {it.courseType == BEGINNER} val beginnerDuration = splitCourses.first.map{it.duration}.sum() val nonBeginnerDuration = splitCourses.second.map{it.duration}.sum() printTabbed(Pair(beginnerDuration,nonBeginnerDuration)) printLine() } fun everyPairOfTrainersThatCouldDeliverJava(courses: List<Course>) { printTitle("Pairs of trainers that could deliver Java") courses.flatMap {it.instructors} .distinct() .filter {it.skills.contains("Java")} .map {it.name} .combinations() .forEach {printTabbed("${it.first} and ${it.second}")} printLine() } functional.using.the.toolkit Using the Functional Toolkit
  • 86. © Instil Software 2017 fun possibleCostsOfJeeWebDevelopment(courses: List<Course>) { printTitle("Possible costs of 'JEE Web Development'") val course = courses.find {it.title.equals("JEE Web Development")} val duration = course?.duration ?: 0 val namesAndCosts = course?.instructors ?.map { Pair(it.name, it.rate * duration)} namesAndCosts?.forEach(::printTabbed) printLine() } fun coursesIdsAndTitlesGroupedByType(courses: List<Course>) { fun process(entry: Entry<CourseType, List<Course>>) { printTabbed(entry.key) entry.value.forEach { println("tt${it.id} ${it.title}")} } printTitle("Course ID's and titles grouped by type") courses.groupBy {it.courseType} .forEach(::process) } functional.using.the.toolkit Using the Functional Toolkit
  • 87. © Instil Software 2017 TDD Demonstration
  • 88. © Instil Software 2017 Spring Demonstration
  • 89. © Instil Software 2017 Creating a Spring Boot Project Key details Dependencies Build tool choice Language choice
  • 90. © Instil Software 2017 Android Demonstration
  • 94. © Instil Software 2017 Conclusions
  • 95. © Instil Software 2017 Conclusions Kotlin is the ideal language for the JVM today
  • 96. © Instil Software 2017 Conclusions Will it be so tomorrow?
  • 97. © Instil Software 2017 Conclusions