Sprint Part 2
otlin Basics
Kirill Rozov
Senior Android Developer
kiryl.rozau
kiryl.rozau@apalon.com
Basic Types
Base types
• Byte

• Short

• Int

• Long

• Float

• Double

• Char

• Boolean
Arrays
byte[] ByteArray
short[] ShortArray
int[] IntArray
long[] LongArray
float[] FloatArray
double[] DoubleArray
boolean[] BooleanArray
char[] CharArray
String Array<String>
String Templates
"the element at $index is $value"
"the element at $index hash code is ${value.hashCode()}”
Variables
Variables
var variable: String = "variable"
Variables
var variable: String = "variable"
Variables
var variable: String = "variable"
Variables
var variable: String = "variable"
Variables
var variable: String = "variable"
variable = “update”
variable = null // Compile error
Variables
variable = “update”
variable = null // Compile error
var variable: String = "variable"
Variables
var variable: String = "variable"
variable = null // Compile error
Variables
var variable: String? = "variable"
variable = null
Variables
var variable: String = "variable"
Variables
val variable: String = "variable"
Variables
val variable: String = "variable"
variable = “update” // Compile error
Variables
val variable: String = "variable"
Variables
val variable: String = "variable"
val variable = "variable"
Explicit variable type
val list = ArrayList<String>()
Explicit variable type
val list: ArrayList<String> = ArrayList<String>()
Explicit variable type
val list: ArrayList<String> = ArrayList<String>()
Explicit variable type
val list: ArrayList<String> = ArrayList()
Explicit variable type
val list: ArrayList<String> = ArrayList()
Explicit variable type
val list: List<String> = ArrayList()
Explicit variable type
Type Checks & Casts: ‘is’ & ’as’
‘is’ & ’as’
if (obj is String) {
val string = obj as String
print(string.length)
}
‘is’ & ’as’
if (obj is String) {
print(obj.length)
}
obj as String
print(obj.length)
‘is’ & ’as’
Safe Casts
val safeObject: String? = obj as? String
Null Safety
Null Safety
val keyValues: Map<String, String> = Collections.emptyMap()
val value = keyValues.get("Sample key")
value.substring(1) // Compile error
Null Safety
val value = keyValues.get("Sample key")
value.substring(1) // Compile error
Null Safety
val value: String? = keyValues.get("Sample key")
value.substring(1) // Compile error
Safe call
val value: String? = keyValues.get("Sample key")
value?.substring(1)
Safe call
val value = keyValues.get("Sample key")
value?.substring(1)
Safe call
val value = keyValues.get("Sample key")
value?.substring(1)
if (value == null) return
Safe call
val value = keyValues.get("Sample key")
value?.substring(1)
if (value == null) return
Smart Cast
val value = keyValues.get("Sample key")
value.substring(1)
if (value == null) return
Null Elvis Operator
val value: String? = keyValues.get("Sample key")
value?.substring(1) ?: "Default"
Operator !!
var value: String? = null
value!!.substring(1)
Operator !!
var value: String? = null
value!!.substring(1)
Control flow
If-else
if (condition) {
…
} else if (…) {
…
} else {
…
}
If-else
if (num > 0) {
return 1
} else if (num < 0) {
return -1
} else {
return 0
}
If-else
return if (num > 0) {
1
} else if (num < 0) {
-1
} else {
0
}
If-else
return if (num > 0) 1
else if (num < 0) -1
else 0
When
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
3 -> print("x == 3")
else -> print("Unknown")
}
When
when (x) {
1, 2, 3 -> print("x == $x”)
else -> print("Unknown")
}
When
when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
When
when {
x in 1..10 -> print("x is in the range")
x in validNumbers -> print("x is valid")
x !in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
for
for (item in collection) print(item)
for (item: String in collection) {
print(item)
}
for (i in collection.indices) {
println(collection[i])
}
for ((index, value) in collection.withIndex()) {
println("the element at $index is $value")
}
Functions
Functions
fun sample(arg1: Boolean): String {
…
}
Functions
fun sample(arg1: Boolean): String {
…
}
Functions
fun sample(arg1: Boolean): String {
…
}
Functions
fun sample(arg1: Boolean): String {
…
}
Functions
fun sample(arg1: Boolean): String {
…
}
Functions
fun scaleX(scale: Float, centerX: Int): Unit {
…
}
Functions
fun scaleX(scale: Float, centerX: Int): Unit {
…
}
Functions
fun scaleX(scale: Float, centerX: Int) {
…
}
Functions
fun concat(s1: String, s2: String): String {
return s1 + s2
}
Functions
fun concat(s1: String, s2: String): String = s1 + s2
Functions
fun concat(s1: String, s2: String) = s1 + s2
Functions Overloading
fun scaleX(scale: Float, centerX: Int)
fun scaleX(scale: Float) = scale(scale, 0)
Function Default Arguments
fun scaleX(scale: Float, centerX: Int = 0)
Function Default Arguments
fun scaleX(scale: Float, centerX: Int = 0)
Functions
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ')
Functions
reformat(str, true, true, false, '_')
Named arguments
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_')
Named arguments
reformat(str, wordSeparator = '_')
Functions
public final class DateUtils {
public static String getFullDate(Date date) {
SimpleDateFormat formatted = new SimpleDateFormat("hh:mm aa - dd MMM yy");
return formatted.format(date);
}
public static String getShortDateYear(Date date) {
SimpleDateFormat formatted = new SimpleDateFormat("dd MMM yy, hh:mm aa");
return formatted.format(date);
}
public static String getShortDate(Date date) {
SimpleDateFormat formatted = new SimpleDateFormat("dd MMM, hh:mm aa");
return formatted.format(date);
}
public static String getTimeOnly(Date date) {
SimpleDateFormat formatted = new SimpleDateFormat("hh:mm aa");
return formatted.format(date);
}
}
Extension Functions
fun Date.getFullDate() =
SimpleDateFormat("hh:mm aa - dd MMM yy").format(this)
fun Date.getShortDateYear() =
SimpleDateFormat("dd MMM yy, hh:mm aa").format(this)
fun Date.getShortDate() =
SimpleDateFormat("dd MMM, hh:mm aa").format(this)
fun Date.getTimeOnly() =
SimpleDateFormat("hh:mm aa").format(this)
Extension Functions
fun Date.getFullDate() =
SimpleDateFormat("hh:mm aa - dd MMM yy").format(this)
Classes
Classes
class Address {
}
Classes
class Address
Properties
class Address {
val id: Long = …
var name: String = …
var street: String = …
}
Lazy Properties
class Address {
val id: Long = …
var name: String = …
var street: String = …
val fullInfo by lazy { "$id $name $street" }
}
Lazy Properties
val fullInfo by lazy { "$id $name $street" }
Lazy Properties
val fullInfo by lazy { "$id $name $street" }
Lazy Properties
val fullInfo by lazy { "$id $name $street" }
Constructors
class Sample constructor(name: String)
Constructors
class Sample constructor(name: String)
Constructors
class Sample(name: String)
Constructors
class Sample(name: String) {
init {
// Initialization go here
}
}
Constructors
class Sample(val name: String)
Constructors
class Sample(val name: String)
Secondary constructors
class Sample(name: String) {
constructor(person: Person): this(person.name)
}
Secondary constructors
class Sample(name: String) {
constructor(person: Person): this(person.name)
}
Secondary constructors
class Sample(name: String) {
constructor(person: Person): this(person.name)
}
Secondary constructors
class Sample {
constructor(firstName: String, secondName: String) {
// Initialization go here
}
}
New class instance
Sample("name")
Sample(name = "name")
Classes defaults
• All non-abstract classes final

Effective Java, Item 17: Design and document for inheritance or else prohibit it.

• All properties final

• All functions final

• Inner classes static

• All members public by default
Visibility Modifiers
• private

• protected

• internal

• public
What is “Modules”?
• An IntelliJ IDEA module

• A Maven project

• A Gradle source set

• A set of files compiled with one invocation of the Ant Task
Data Classes
class Point(var x: Float, val y: Float) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Point
return x == other.x && y == other.y
}
override fun hashCode() = 31 * x.hashCode() + y.hashCode()
override fun toString() = "Point(x=$x, y=$y)"
}
Data Classes
data class Point(var x: Float, val y: Float)
Data Classes
data class Point(var x: Float, val y: Float)
Data classes
• Implement equals(), hashCode()
• toString() of the form “Point(x=12.3,y=59.1)”
• Add componentN() functions corresponding to the properties in their order
of declaration

• Add copy() function
Data classes
for (point in points) {
print("(${point.x}, ${point.y})")
}
Destructive declaration
for ((x, y) in points) {
print("($x, $y)")
}
Destructive declaration
for ((x, y) in points) {
print("($x, $y)")
}
Enum classes
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
Enum classes
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
Inheritance
Inheritance
class Point(var x: Float, val y: Float)
Inheritance
open class Point(var x: Float, val y: Float)
Inheritance
open class Point(var x: Float, val y: Float)
class Point3D(var x: Float, var y: Float, val z: Float)
Inheritance
open class Point(var x: Float, val y: Float)
class Point3D(var x: Float, var y: Float, val z: Float) : Point(x, y)
Inheritance
open class Point(var x: Float, val y: Float)
class Point3D(x: Float, y: Float, val z: Float) : Point(x, y)
Inheritance
open class Point(var x: Float, val y: Float)
class Point3D : Point {
val z: Float
constructor(x: Float, y: Float, z: Float) : super(x, y) {
this.z = z
}
}
Interfaces
Interfaces
interface SampleInterface {
val prop: Int
fun bar()
fun foo()
}
class SampleClass : SampleInterface {
override val prop = 20
override fun bar() {}
override fun foo() {}
}
Interfaces
class SampleClass : SuperClass, Interface1, Interface2
Default functions
interface MyInterface {
val prop: Int
fun bar() {
print("Bar")
}
fun foo()
}
Collections
Collections
Immutable Mutable
List listOf() mutableListOf()
Set setOf() mutableSetOf()
Map mapOf() mutableMapOf()
Additional features
• Operator overloading

• Type Aliases

• Inline functions

• Lambdas

• High-Order Functions

• Method reference

• Sealed classes

• Delegation

• Try-with-resource

• Object expression & declaration

• DSL

• Multi value return

• Corountines

• Improved generics
Supporting IDE
IntelliJ IDEA Android Studio Eclipse
Thanks!
goo.gl/hXpK4c

Kotlin Basics - Apalon Kotlin Sprint Part 2