Iskuhi Sargsyan
Statically typed programming language
for modern multiplatform applications
Statically Typed
//java
final String companyName = "0+X";
//kotlin
val companyName = "0+x"
Why Kotlin?
• Concise
• Safe
• Interoperable
• Tool-friendly
Looking under the hood
• Data Classes
• Null-safety
• Smart Casts
• High order functions
• Inline Functions
• Extension functions
• Standard Extension Functions
Data Classes
Classes
class Store(val name: String,
var address: String?)
public final class Store {
@NotNull
private final String name;
@Nullable
private String address;
@NotNull
public final String getName() {
return this.name;
}
@Nullable
public final String getAddress() {
return this.address;
}
public final void setAddress(@Nullable String var1) {
this.address = var1;
}
public Store(@NotNull String name, @Nullable String address) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.address = address;
}
}
Data Classes
data class Store(val name: String,
var address: String?)
public final class Store {
@NotNull
private final String name;
@Nullable
private String address;
@NotNull
public final String getName() {
return this.name;
}
@Nullable
public final String getAddress() {
return this.address;
}
public final void setAddress(@Nullable String var1) {
this.address = var1;
}
public Store(@NotNull String name, @Nullable String address) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.address = address;
}
@NotNull
public final String component1() {
return this.name;
}
@Nullable
public final String component2() {
return this.address;
}
@NotNull
public final Store copy(@NotNull String name, @Nullable String address) {
Intrinsics.checkParameterIsNotNull(name, "name");
return new Store(name, address);
}
// $FF: synthetic method
// $FF: bridge method
@NotNull
public static Store copy$default(Store var0, String var1, String var2, int var3, Object var4) {
if((var3 & 1) != 0) {
var1 = var0.name;
}
if((var3 & 2) != 0) {
var2 = var0.address;
}
return var0.copy(var1, var2);
}
public String toString() {
return "Store(name=" + this.name + ", address=" + this.address + ")";
}
public int hashCode() {
return (this.name != null?this.name.hashCode():0) * 31 + (this.address != null?this.address.hashCode():0);
}
public boolean equals(Object var1) {
if(this != var1) {
if(var1 instanceof Store) {
Store var2 = (Store)var1;
if(Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.address, var2.address)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
public String toString() {
return “Store(name=" + this.name + “, address=" + this.address +")";
}
public int hashCode() {
return (this.name != null?this.name.hashCode():0) * 31 + (this.address !=
null?this.address.hashCode():0);
}
public boolean equals(Object var1) {
if(this != var1) {
if(var1 instanceof Store) {
Store var2 = (Store)var1;
if(Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.address,
var2.address)) {
return true;
}
}
return false;
} else {
return true;
}
componentN( )
@NotNull
public final String component1() {
return this.name;
}
@Nullable
public final String component2() {
return this.address;
}
Destructuring Declaration
val store = Store("ICA Nära", "Sveavägen 118")
val (name, address) = store
println(“$name address is $address") // prints "ICA Nära address is
Sveavägen 118 "
val map = hashMapOf(1 to "ICA Nära Sveavägen",
2 to "ICA Nära Hötorget”)
for ((i, n) in map){
println("Entry in map: $i: $n")
}
copy( )
@NotNull
public final Store copy(@NotNull String name, @Nullable String address) {
Intrinsics.checkParameterIsNotNull(name, "name");
return new Store(name, address);
}
// $FF: synthetic method
// $FF: bridge method
@NotNull
public static Store copy$default(Store var0, String var1, String var2, int var3, Object var4) {
if((var3 & 1) != 0) {
var1 = var0.name;
}
if((var3 & 2) != 0) {
var2 = var0.address;
}
return var0.copy(var1, var2);
}
copy( )
val store = Store(name = "ICA Nära",address = "Sveavägen 118")
val store1 = store.copy()
// Store(name=ICA Nära, address=Sveavägen 118)
val store2 = store.copy(name = "ICA Kvantum")
// Store(name=ICA Maxi, address=Sveavägen 118)
val store3 = store.copy(address = null)
// Store(name=CA Nära, address=null)
val store4 = store.copy(name = "ICA Kvantum", address = "Solna Centrum")
// Store(name=ICA Kvantum, address=Solna Centrum)
Java fields and Kotlin
properties
//java
private String address;
public final String getAddress() {
return this.address;
}
public final void setAddress(@Nullable String var1) {
this.address = var1;
}
//kotlin
var address: String
Null Safety
Null Safety
// won't compile
var storeName:String = "ICA Kvantum"
storeName = null
var storeName1: String? = getName()
storeName1.length
Checking for null in
conditions
if (storeName != null && storeName.length > 0) {
print("String of length ${storeName.length}")
} else {
print("Empty string")
}
Safe calls
name?.length
store?.address?.city
!!operator
var storeName: String? = getString()
storeName!!.length
Null Safe Scoping
storeName?.let {
it.length
}
Elvis Operator
var storeName: String? = getString()
return storeName?.length ?: -1
Type Checks and
Casts
Smart Casts
val mixedTypeList: List<Any> = listOf("I", "am", 5, "feet", 9.5, "inches", "tall")
for(value in mixedTypeList) {
if (value is String) {
println("String: '$value' of length ${value.length} ")
} else if (value is Int) {
println("Integer: '$value'")
} else if (value is Double) {
println("Double: '$value' with Ceil value ${Math.ceil(value)}")
} else {
println("Unknown Type")
}
}
Object obj = “Simple sample in JAVA”;
if(obj instanceof String) {
// Explicit Casting to `String`
String str = (String) obj;
System.out.println("Found a String of length " + str.length());
}
Smart Casts
//x is automatically cast to string on the right-hand side of `&&`
if (name is String && name.length > 0) {
print(name.length) // x is automatically cast to String
}
Unsafe cast operator as
val obj: Any = 123
val str: String = obj as String
// Throws java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.String
val obj: Any? = null
val str: String = obj as String
// Throws kotlin.TypeCastException: null cannot be cast to non-null type kotlin.String
Safe cast operator as?
val obj: Any? = null
val str: String? = obj as? String? // Works
println(str) // Prints null
High order functions
High Order Functions
fun operate (v1: Int, v2: Int, fn: (Int, Int) -> Int): Int {
return fn (v1, v2)
}
fun sum (x1: Int, x2: Int) = x1 + x2
fun sub (x1: Int, x2: Int) = x1 - x2
println("The sum of 10 and 5 is ${operate (10, 5, ::sum)}")
println(“Sub… of 100 and 40 is ${operate (100, 40, ::sub)}")
Lambda expressions
fun operate (v1: Int, v2: Int, fn: (Int, Int) -> Int): Int {
return fn (v1, v2)
}
println("The sum of 10 and 5 is ${operate (2, 3,{x, y -> x+y})}")
println(“Sub… of 100 and 40 is ${operate (100,40,{x, y -> x-y})}”)
println(“Sub… of 100 and 40 is ${operate (100,40){x, y -> x-y}}")
Anonymous Functions
fun operate (v1: Int, v2: Int, fn: (Int, Int) -> Int): Int {
return fn (v1, v2)
}
println(“The sum of 10 and 5 is
${ operate (2, 3,fun(x1:Int, x2:Int):Int {return x1 + x2})}")
println ("Sub... of 100 and 40 is
${operate (100,40,fun(x:Int, y:Int) = x + y )}")
Inline Functions
inline fun operate(v1:Int, v2:Int, fn:(Int, Int)->Int):Int {
return fn (v1, v2)
}
println("The sum of 10 and 5 is ${operate (2, 3,x+y)}")
Extension Functions
Extension Functions
fun String.upperCaseFirstLetter(): String {
return this.substring(0, 1).toUpperCase().plus(this.substring(1))
}
val name ="ica"
print(name.upperCaseFirstLetter())
public class StringUtilskt {
public static String upperCaseFirstLetter(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
Standard Extension
Functions
apply
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
fun openBankIdIntent(activity: Activity, autostartToken: String) {
val intent = Intent()
intent.`package` = "com.bankid.bus"
intent.action = Intent.ACTION_VIEW
intent.data = Uri.parse("bankid:///?autostarttoken=" + autostartToken + "&redirect=null")
activity.startActivity(intent)
}
fun Activity.openBankIdIntent(autoStartToken: String) {
val intent = Intent()
intent.apply {
`package` = "com.bankid.bus"
action = Intent.ACTION_VIEW
data = Uri.parse("bankid:///?autostarttoken=" + autostartToken + "&redirect=null")
}
this.startActivity(intent)
}
run
public inline fun <T, R> T.run(block: T.() -> R): R = block()
val generator = PasswordGenerator()
generator.length = 10
generator.lowers = false
generator.numbers = true
val password: Password = generator.generate()
val password: Password = PasswordGenerator().run {
length = 10
lowers = false
numbers = true
generate()
}
Let
public inline fun <T, R> T.let(block:(T)->R): R = block(this)
store?.let {
viewBinding.marketingName.text = store.marketingName
viewBinding.storeIcon.setImageResource(…)
}
How to start with Kotlin
• Online playground - http://try.kotl.in
• Converting a Java File to Kotlin File
Thank you

Benefits of Kotlin

  • 1.
  • 2.
    Statically typed programminglanguage for modern multiplatform applications
  • 3.
    Statically Typed //java final StringcompanyName = "0+X"; //kotlin val companyName = "0+x"
  • 4.
    Why Kotlin? • Concise •Safe • Interoperable • Tool-friendly
  • 5.
  • 6.
    • Data Classes •Null-safety • Smart Casts • High order functions • Inline Functions • Extension functions • Standard Extension Functions
  • 7.
  • 8.
    Classes class Store(val name:String, var address: String?)
  • 9.
    public final classStore { @NotNull private final String name; @Nullable private String address; @NotNull public final String getName() { return this.name; } @Nullable public final String getAddress() { return this.address; } public final void setAddress(@Nullable String var1) { this.address = var1; } public Store(@NotNull String name, @Nullable String address) { Intrinsics.checkParameterIsNotNull(name, "name"); super(); this.name = name; this.address = address; } }
  • 10.
    Data Classes data classStore(val name: String, var address: String?)
  • 11.
    public final classStore { @NotNull private final String name; @Nullable private String address; @NotNull public final String getName() { return this.name; } @Nullable public final String getAddress() { return this.address; } public final void setAddress(@Nullable String var1) { this.address = var1; } public Store(@NotNull String name, @Nullable String address) { Intrinsics.checkParameterIsNotNull(name, "name"); super(); this.name = name; this.address = address; } @NotNull public final String component1() { return this.name; } @Nullable public final String component2() { return this.address; } @NotNull public final Store copy(@NotNull String name, @Nullable String address) { Intrinsics.checkParameterIsNotNull(name, "name"); return new Store(name, address); } // $FF: synthetic method // $FF: bridge method @NotNull public static Store copy$default(Store var0, String var1, String var2, int var3, Object var4) { if((var3 & 1) != 0) { var1 = var0.name; } if((var3 & 2) != 0) { var2 = var0.address; } return var0.copy(var1, var2); } public String toString() { return "Store(name=" + this.name + ", address=" + this.address + ")"; } public int hashCode() { return (this.name != null?this.name.hashCode():0) * 31 + (this.address != null?this.address.hashCode():0); } public boolean equals(Object var1) { if(this != var1) { if(var1 instanceof Store) { Store var2 = (Store)var1; if(Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.address, var2.address)) { return true; } } return false; } else { return true; } } }
  • 12.
    public String toString(){ return “Store(name=" + this.name + “, address=" + this.address +")"; } public int hashCode() { return (this.name != null?this.name.hashCode():0) * 31 + (this.address != null?this.address.hashCode():0); } public boolean equals(Object var1) { if(this != var1) { if(var1 instanceof Store) { Store var2 = (Store)var1; if(Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.address, var2.address)) { return true; } } return false; } else { return true; }
  • 13.
    componentN( ) @NotNull public finalString component1() { return this.name; } @Nullable public final String component2() { return this.address; }
  • 14.
    Destructuring Declaration val store= Store("ICA Nära", "Sveavägen 118") val (name, address) = store println(“$name address is $address") // prints "ICA Nära address is Sveavägen 118 " val map = hashMapOf(1 to "ICA Nära Sveavägen", 2 to "ICA Nära Hötorget”) for ((i, n) in map){ println("Entry in map: $i: $n") }
  • 15.
    copy( ) @NotNull public finalStore copy(@NotNull String name, @Nullable String address) { Intrinsics.checkParameterIsNotNull(name, "name"); return new Store(name, address); } // $FF: synthetic method // $FF: bridge method @NotNull public static Store copy$default(Store var0, String var1, String var2, int var3, Object var4) { if((var3 & 1) != 0) { var1 = var0.name; } if((var3 & 2) != 0) { var2 = var0.address; } return var0.copy(var1, var2); }
  • 16.
    copy( ) val store= Store(name = "ICA Nära",address = "Sveavägen 118") val store1 = store.copy() // Store(name=ICA Nära, address=Sveavägen 118) val store2 = store.copy(name = "ICA Kvantum") // Store(name=ICA Maxi, address=Sveavägen 118) val store3 = store.copy(address = null) // Store(name=CA Nära, address=null) val store4 = store.copy(name = "ICA Kvantum", address = "Solna Centrum") // Store(name=ICA Kvantum, address=Solna Centrum)
  • 17.
    Java fields andKotlin properties //java private String address; public final String getAddress() { return this.address; } public final void setAddress(@Nullable String var1) { this.address = var1; } //kotlin var address: String
  • 18.
  • 19.
    Null Safety // won'tcompile var storeName:String = "ICA Kvantum" storeName = null var storeName1: String? = getName() storeName1.length
  • 20.
    Checking for nullin conditions if (storeName != null && storeName.length > 0) { print("String of length ${storeName.length}") } else { print("Empty string") }
  • 21.
  • 22.
    !!operator var storeName: String?= getString() storeName!!.length
  • 23.
  • 24.
    Elvis Operator var storeName:String? = getString() return storeName?.length ?: -1
  • 25.
  • 26.
    Smart Casts val mixedTypeList:List<Any> = listOf("I", "am", 5, "feet", 9.5, "inches", "tall") for(value in mixedTypeList) { if (value is String) { println("String: '$value' of length ${value.length} ") } else if (value is Int) { println("Integer: '$value'") } else if (value is Double) { println("Double: '$value' with Ceil value ${Math.ceil(value)}") } else { println("Unknown Type") } }
  • 27.
    Object obj =“Simple sample in JAVA”; if(obj instanceof String) { // Explicit Casting to `String` String str = (String) obj; System.out.println("Found a String of length " + str.length()); }
  • 28.
    Smart Casts //x isautomatically cast to string on the right-hand side of `&&` if (name is String && name.length > 0) { print(name.length) // x is automatically cast to String }
  • 29.
    Unsafe cast operatoras val obj: Any = 123 val str: String = obj as String // Throws java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String val obj: Any? = null val str: String = obj as String // Throws kotlin.TypeCastException: null cannot be cast to non-null type kotlin.String
  • 30.
    Safe cast operatoras? val obj: Any? = null val str: String? = obj as? String? // Works println(str) // Prints null
  • 31.
  • 32.
    High Order Functions funoperate (v1: Int, v2: Int, fn: (Int, Int) -> Int): Int { return fn (v1, v2) } fun sum (x1: Int, x2: Int) = x1 + x2 fun sub (x1: Int, x2: Int) = x1 - x2 println("The sum of 10 and 5 is ${operate (10, 5, ::sum)}") println(“Sub… of 100 and 40 is ${operate (100, 40, ::sub)}")
  • 33.
    Lambda expressions fun operate(v1: Int, v2: Int, fn: (Int, Int) -> Int): Int { return fn (v1, v2) } println("The sum of 10 and 5 is ${operate (2, 3,{x, y -> x+y})}") println(“Sub… of 100 and 40 is ${operate (100,40,{x, y -> x-y})}”) println(“Sub… of 100 and 40 is ${operate (100,40){x, y -> x-y}}")
  • 34.
    Anonymous Functions fun operate(v1: Int, v2: Int, fn: (Int, Int) -> Int): Int { return fn (v1, v2) } println(“The sum of 10 and 5 is ${ operate (2, 3,fun(x1:Int, x2:Int):Int {return x1 + x2})}") println ("Sub... of 100 and 40 is ${operate (100,40,fun(x:Int, y:Int) = x + y )}")
  • 35.
    Inline Functions inline funoperate(v1:Int, v2:Int, fn:(Int, Int)->Int):Int { return fn (v1, v2) } println("The sum of 10 and 5 is ${operate (2, 3,x+y)}")
  • 36.
  • 37.
    Extension Functions fun String.upperCaseFirstLetter():String { return this.substring(0, 1).toUpperCase().plus(this.substring(1)) } val name ="ica" print(name.upperCaseFirstLetter()) public class StringUtilskt { public static String upperCaseFirstLetter(String str) { return str.substring(0, 1).toUpperCase() + str.substring(1); } }
  • 38.
  • 39.
    apply public inline fun<T> T.apply(block: T.() -> Unit): T { block(); return this } fun openBankIdIntent(activity: Activity, autostartToken: String) { val intent = Intent() intent.`package` = "com.bankid.bus" intent.action = Intent.ACTION_VIEW intent.data = Uri.parse("bankid:///?autostarttoken=" + autostartToken + "&redirect=null") activity.startActivity(intent) } fun Activity.openBankIdIntent(autoStartToken: String) { val intent = Intent() intent.apply { `package` = "com.bankid.bus" action = Intent.ACTION_VIEW data = Uri.parse("bankid:///?autostarttoken=" + autostartToken + "&redirect=null") } this.startActivity(intent) }
  • 40.
    run public inline fun<T, R> T.run(block: T.() -> R): R = block() val generator = PasswordGenerator() generator.length = 10 generator.lowers = false generator.numbers = true val password: Password = generator.generate() val password: Password = PasswordGenerator().run { length = 10 lowers = false numbers = true generate() }
  • 41.
    Let public inline fun<T, R> T.let(block:(T)->R): R = block(this) store?.let { viewBinding.marketingName.text = store.marketingName viewBinding.storeIcon.setImageResource(…) }
  • 42.
    How to startwith Kotlin • Online playground - http://try.kotl.in • Converting a Java File to Kotlin File
  • 43.