├── .idea
├── codeStyles
│ └── codeStyleConfig.xml
├── kotlinc.xml
├── libraries
│ └── KotlinJavaRuntime.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
└── vcs.xml
├── KotlinTutorials.iml
├── README.md
└── src
├── 01_hello_world.kt
├── 02_explore_first_app.kt
├── 03_comments.kt
├── 04_variables_data_types.kt
├── 05_kotlin_basics.kt
├── 06_Person.kt
├── 06_kotlin_basics.kt
├── 07_data_types.kt
├── 08_string_interpolation.kt
├── 09_ranges.kt
├── 10_default_functions.kt
├── 10_if_expression.kt
├── 11_when_expression.kt
├── 12_for_loop.kt
├── 13_while_loop.kt
├── 14_do_while.kt
├── 15_break_keyword.kt
├── 16_continue_keyword.kt
├── 17_functions_basics.kt
├── 18_functions_as_expressions.kt
├── 21_named_parameters.kt
├── 22_extension_function_one.kt
├── 23_extension_function_two.kt
├── 24_infix_function.kt
├── 25_tailrec_function.kt
├── 26_class_and_constructor.kt
├── 27_inheritance.kt
├── 28_overriding_methods_properties.kt
├── 29_inheritance_primary_secondary_constructor.kt
├── 30_abstract_class.kt
├── 31_interface.kt
├── 32_data_class.kt
├── 33_object_declaration.kt
├── 34_1_enum_class
├── 34_2_sealed_class.kt
├── 34_companion_object.kt
├── 35_lambdas_higher_order_functions.kt
├── 36_lambdas_example_two.kt
├── 37_lambdas_closures.kt
├── 38_it_keyword_lambdas.kt
├── 39_with_apply_functions.kt
├── 40_arrays.kt
├── 41_list.kt
├── 42_map_hashmap.kt
├── 43_set_hashset.kt
├── 44_filter_map_sorting.kt
├── 45_predicate.kt
├── 46_null_safety.kt
├── 47_lateinit_keyword.kt
├── 48_lazy_keyword.kt
├── 49_with_scope_function.kt
├── 50_apply_scope_function.kt
├── 51_also_scope_function.kt
├── 52_let_scope_function.kt
├── 53_run_scope_function.kt
├── 60_thread_example.kt
├── 61_first_coroutine.kt
├── 62_runBlocking_and_delay.kt
├── 63_custom_suspending_function.kt
├── 64_launch_coroutine_builder.kt
├── 65_async_coroutine_builder.kt
├── 66_a_runBlocking_coroutine_builder.kt
├── 66_b_test_case.kt
├── 68_cooperative_coroutine_suspend_function.kt
├── 69_isActive_flag_cooperative_coroutine.kt
├── 70_exception_handling.kt
├── 71_withContext_coroutine_builder.kt
├── 72_withTimeout_coroutine_builder.kt
├── 73_withTimeoutOrNull_coroutine_builder.kt
├── 74_sequential_suspending_functions.kt
├── 75_concurrency_within_coroutine.kt
├── 76_lazy_async.kt
├── 77_CoroutineScope.kt
├── 78_CoroutineContext_and_Dispatchers.kt
├── MyJavaFile.java
└── myKotlinInteroperability.kt
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/libraries/KotlinJavaRuntime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/KotlinTutorials.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kotlin Programming Tutorial for Beginners
2 | Learn Kotlin Programming, its basics and Fundamentals from scratch.
3 |
4 | ## Topics to be covered
5 | 0. Overview
6 | - Course introduction, prequisites and software required
7 | 1. Installation
8 | - Install required softwares for Windows, MAC and Linux ( Ubuntu )
9 | 2. Getting Started with Kotlin Programming
10 | - Run your first app in Kotlin
11 | 3. Exploring Data Types and Variables
12 | - Data Types and Variables
13 | - String, Literals and String Interpolation
14 | - Comments
15 | 4. Constants, Variables and Data Types
16 | 5. Control Flow Statements
17 | - IF ELSE
18 | - IF Expressions
19 | - WHEN Expressions
20 | 6. Loop Control Statements
21 | - What are Iterators?
22 | - FOR Loop and how it works
23 | - WHILE Loop
24 | - DO WHILE Loop
25 | - BREAK statements
26 | - CONTINUE keyword
27 | - Labelled FOR Loop
28 | 7. Functions and Interoperability
29 | - Declaring functions
30 | - Interoperability with Java code
31 | - Function as Expressions
32 | - Extension Functions
33 | - Infix Functions
34 | - Default Parameters
35 | - Named Parameters
36 | - Tailrec Functions
37 | 8. Object Oriented Programming in Kotlin
38 | - Defining Class and creating Objects
39 | - INIT block
40 | - Primary and Secondary Constructors
41 | - Properties ( Field variables )
42 | - Inheritance
43 | - Method and Property Overriding
44 | - Polymorphism
45 | - Abstract Class, Property and Method
46 | - Interface
47 | - Data Class
48 | - Object Declaration
49 | - Enum class
50 | - Sealed class
51 | - Companion Object
52 | 9. Functional Programming in Koltin
53 | - Lambdas
54 | - Higher-Order Functions
55 | - Closures
56 | - 'it' keyword
57 | - 'with' function
58 | - 'apply' function
59 | 10. Collections in Kotlin
60 | - Arrays
61 | - List
62 | - Map and HashMap
63 | - Set and HashSet
64 | 11. Sorting and Filtering
65 | - "filter" function
66 | - "map" function
67 | - Predicates: all, any, find, count.
68 | 12. Kotlin NULL Safety
69 | - Safe call
70 | - with Let
71 | - Elvis
72 | - Lateinit keyword
73 | - Lazy delegation and 'lateinit' vs. 'lazy'
74 | 13. Scope Functions
75 | - with
76 | - apply
77 | - let
78 | - also
79 | - run
80 | 14. Coroutines
81 | - What are Coroutines? How are they related to Threads?
82 | - launch, async, runBlocking, withContext, withTimeoutOrNull,
83 | - Suspending function
84 | - Cancellation and Timeouts
85 | - Cooperative suspending functions and isActive flag
86 | - Exception Handling in Coroutines
87 | - Sequential execution of suspending function in Coroutines
88 | - Concurrency within Coroutine
89 | - lazy 'async'
90 | - CoroutineScope and CoroutineContext
91 | - Dispacthers: Confined dispatcher, Default Dispatcher, and Unconfined Displatcher
92 | 15. Conclusion
93 |
94 | ## Authors
95 |
96 | * **Sriyank Siddhartha**
97 |
--------------------------------------------------------------------------------
/src/01_hello_world.kt:
--------------------------------------------------------------------------------
1 |
2 | // Hello World App
3 |
4 | fun main(args: Array) {
5 | print("Hello World")
6 | }
7 |
--------------------------------------------------------------------------------
/src/02_explore_first_app.kt:
--------------------------------------------------------------------------------
1 |
2 | // Explore First App
3 |
4 | fun main(args: Array) {
5 |
6 | println("Hello World")
7 |
8 | println(10)
9 |
10 | println(true)
11 |
12 | println(10 / 2)
13 |
14 | println(94.2f)
15 |
16 | println(9 - 3)
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/03_comments.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /*
5 | * This is comment line 1
6 | *
7 | * This is comment line 2
8 | *
9 | * This is main function. Entry point of the application.
10 | * */
11 |
12 | fun main(args: Array) { // This is inline comment ...
13 | print("Hello World")
14 | }
15 |
--------------------------------------------------------------------------------
/src/04_variables_data_types.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This is main function. Entry point of the application.
4 | * */
5 | fun main(args: Array) {
6 |
7 | var myNumber = 10 // Int
8 | var myDecimal = 1.0 // Float
9 | var isActive = true // Boolean
10 |
11 | var myString: String // Mutable String
12 | myString = "Hello World"
13 | myString = "Another World"
14 |
15 | val myAnotherString = "My constant string value" // Immutable String
16 | // myAnotherString = "some value" // NOT ALLOWED, since it is immutable
17 |
18 | print(myNumber)
19 | }
20 |
--------------------------------------------------------------------------------
/src/05_kotlin_basics.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * This is main function. Entry point of the application.
5 | * */
6 | fun main(args: Array) {
7 |
8 | var personObj = Person()
9 | personObj.name = "Steve"
10 |
11 | print("The name of the person is ${personObj.name}")
12 | }
13 |
14 | class Person {
15 |
16 | var name: String = ""
17 | }
18 |
--------------------------------------------------------------------------------
/src/06_Person.kt:
--------------------------------------------------------------------------------
1 |
2 | class Persson(var name: String ) {
3 |
4 | fun display() {
5 | print("The name of the person is ${name}")
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/06_kotlin_basics.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This is main function. Entry point of the application.
4 | * */
5 | fun main(args: Array) {
6 |
7 | var personObj = Persson("Steve")
8 |
9 | personObj.display()
10 | }
11 |
--------------------------------------------------------------------------------
/src/07_data_types.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Explore Data Types in Kotlin
4 | * */
5 |
6 | fun main(args: Array) {
7 |
8 | var name: String
9 | name = "Kevin"
10 |
11 | var age: Int = 10
12 | var myAge = 10
13 |
14 | var isAlive: Boolean = true
15 | var marks: Float = 97.4F
16 | var percentage: Double = 90.78
17 | var gender: Char = 'M'
18 |
19 | print(marks)
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/08_string_interpolation.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Explore String Interpolation in Kotlin
4 | * */
5 | fun main(args: Array) {
6 |
7 | var rect = Rectangle()
8 | rect.length = 5
9 | rect.breadth = 3
10 |
11 | print("The length of the rectangle is ${rect.length} and breadth is ${rect.breadth}. The area is ${rect.length * rect.breadth}")
12 |
13 | }
14 |
15 | class Rectangle {
16 |
17 | var length: Int = 0
18 | var breadth: Int = 0
19 | }
20 |
--------------------------------------------------------------------------------
/src/09_ranges.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * Explore Ranges
5 | * */
6 | fun main(args: Array) {
7 |
8 | var r1 = 1..5
9 | // This range contains number 1, 2, 3, 4, 5
10 |
11 | val r2 = 5 downTo 1
12 | // This range contains number 5, 4, 3, 2, 1
13 |
14 | val r3 = 5 downTo 1 step 2
15 | // This range contains number 5, 3, 1
16 |
17 | val r4 = 'a'..'z'
18 | // This range contains the values from "a", "b", "c" . . . "z"
19 |
20 | var isPresent = 'c' in r4
21 |
22 | var countDown = 10.downTo(1)
23 | // This range contains number 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
24 |
25 | var moveUp = 1.rangeTo(10)
26 | // This range contains number 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/10_default_functions.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Default Functions
4 | * */
5 | fun main(args: Array) {
6 |
7 | var result = findVolume(2, 3)
8 | print(result)
9 | }
10 |
11 | fun findVolume(length: Int, breadth: Int, height: Int = 10): Int {
12 |
13 | return length * breadth * height
14 | }
15 |
--------------------------------------------------------------------------------
/src/10_if_expression.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * IF as Expression
4 | * */
5 | fun main(args: Array) {
6 |
7 | val a = 2
8 |
9 | val b = 5
10 |
11 | var maxValue: Int = if (a > b) {
12 | print("a is greater")
13 | a
14 | } else {
15 | print("b is greater")
16 | b
17 | }
18 |
19 | println(maxValue)
20 | }
21 |
--------------------------------------------------------------------------------
/src/11_when_expression.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * WHEN as Expression
5 | * */
6 | fun main(args: Array) {
7 |
8 | val x = 100
9 |
10 | val str: String = when (x) {
11 |
12 | 1 -> "x is 1"
13 | 2 -> "x is 2"
14 | else -> {
15 | "x value is unknown"
16 | "x is an alien"
17 | }
18 | }
19 |
20 | println(str)
21 | }
22 |
--------------------------------------------------------------------------------
/src/12_for_loop.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * FOR Loop
5 | * */
6 | fun main(args: Array) {
7 |
8 | for (i in 1..10) {
9 |
10 | if (i % 2 == 0) {
11 | println(i)
12 | }
13 | }
14 |
15 | println()
16 |
17 | for (i in 10 downTo 0) {
18 |
19 | if (i % 2 == 0) {
20 | println(i)
21 | }
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/13_while_loop.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * WHILE Loop
5 | * */
6 | fun main(args: Array) {
7 |
8 | var i = 0
9 | while (i <= 10) {
10 | if (i % 2 == 0) {
11 | println(i)
12 | }
13 | i++
14 | }
15 |
16 | println()
17 |
18 | var j = 10
19 | while (j >= 0) {
20 | if (j % 2 == 0) {
21 | println(j)
22 | }
23 | j--
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/14_do_while.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * DO WHILE Loop
5 | * */
6 | fun main(args: Array) {
7 |
8 | var i = 0
9 |
10 | do {
11 | if (i % 2 == 0) {
12 | println(i)
13 | }
14 | i++
15 | } while (i <= 10)
16 |
17 | println()
18 |
19 | var j = 10
20 |
21 | do {
22 | if (j % 2 == 0) {
23 | println(j)
24 | }
25 | j--
26 | } while (j >= 0)
27 | }
28 |
--------------------------------------------------------------------------------
/src/15_break_keyword.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * BREAK Keyword and Labelled FOR Loop
5 | * */
6 | fun main(args: Array) {
7 |
8 | for (i in 0..4) {
9 | println(i)
10 |
11 | if (i == 2) {
12 | break
13 | }
14 | }
15 |
16 | println()
17 |
18 | myLoop@ for (i in 1..3) {
19 | for (j in 1..3) {
20 | println("$i $j")
21 | if (i == 2 && j == 2)
22 | break@myLoop
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/16_continue_keyword.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * CONTINUE Keyword and Labelled FOR Loop
5 | * */
6 | fun main(args: Array) {
7 |
8 | for (i in 1..3) {
9 | if (i == 2)
10 | continue
11 | println(i)
12 | }
13 |
14 |
15 | myLoop@ for (i in 1..3) {
16 | for (j in 1..3) {
17 | if (i == 2 && j == 2) {
18 | continue@myLoop
19 | }
20 | println("$i $j")
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/17_functions_basics.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * FUNCTIONS Basics
4 | * */
5 | fun main(args: Array) {
6 |
7 |
8 | var sum = add(2, 4)
9 |
10 | println("Sum is " + sum)
11 | }
12 |
13 | fun add(a: Int, b: Int): Int {
14 | return a + b
15 | }
16 |
--------------------------------------------------------------------------------
/src/18_functions_as_expressions.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * FUNCTIONS as Expressions
5 | * */
6 | fun main(args: Array) {
7 |
8 | var largeValue = max(4, 6)
9 |
10 | println("The greater number is $largeValue")
11 | }
12 |
13 | fun max(a: Int, b: Int): Int
14 | = if (a > b) {
15 | println("$a is greater")
16 | a
17 | } else {
18 | println("$b is greater")
19 | b
20 | }
21 |
--------------------------------------------------------------------------------
/src/21_named_parameters.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * Named Parameters
5 | * */
6 | fun main(args: Array) {
7 |
8 | var result = findTheVolume(breadth = 2, length = 3)
9 | print(result)
10 | }
11 |
12 | fun findTheVolume(length: Int, breadth: Int, height: Int = 10): Int {
13 |
14 | return length * breadth * height
15 | }
16 |
--------------------------------------------------------------------------------
/src/22_extension_function_one.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Extension Functions: EXAMPLE ONE
4 | * */
5 | fun main(args: Array) {
6 |
7 | var student = Studentt()
8 | println("Pass status: " + student.hasPassed(57))
9 |
10 | println("Scholarship Status: " + student.isScholar(57))
11 | }
12 |
13 | fun Studentt.isScholar(marks: Int): Boolean {
14 | return marks > 95
15 | }
16 |
17 | class Studentt { // OUR OWN CLASS
18 |
19 | fun hasPassed(marks: Int): Boolean {
20 | return marks > 40
21 | }
22 | }
--------------------------------------------------------------------------------
/src/23_extension_function_two.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Extension Functions: EXAMPLE TWO
4 | * */
5 | fun main(args: Array) {
6 |
7 | var str1: String = "Hello "
8 | var str2: String = "World"
9 |
10 | var str3: String = "Hey "
11 |
12 | println(str3.add(str1, str2))
13 |
14 | val x: Int = 6
15 | val y: Int = 10
16 |
17 | val greaterVal = x.greaterValue(y)
18 |
19 | println(greaterVal)
20 | }
21 |
22 | fun String.add(s1: String, s2: String): String {
23 |
24 | return this + s1 + s2
25 | }
26 |
27 | fun Int.greaterValue(other: Int): Int {
28 |
29 | if (this > other)
30 | return this
31 | else
32 | return other
33 | }
34 |
--------------------------------------------------------------------------------
/src/24_infix_function.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * INFIX FUNCTIONS
4 | * */
5 | fun main(args: Array) {
6 |
7 | val x: Int = 6
8 | val y: Int = 10
9 |
10 | val greaterVal = x findGreaterValue y // x.findGreaterValue(y)
11 |
12 | println(greaterVal)
13 | }
14 |
15 | infix fun Int.findGreaterValue(other: Int): Int { // INFIX and Extension Func
16 |
17 | if (this > other)
18 | return this
19 | else
20 | return other
21 | }
22 |
23 | /*
24 | * 1. All INFIX Functions are Extension functions
25 | * But all Extension functions are not INFIX
26 | * 2. INFIX Functions just have ONE PARAMETER
27 | * */
28 |
--------------------------------------------------------------------------------
/src/25_tailrec_function.kt:
--------------------------------------------------------------------------------
1 | import java.math.BigInteger
2 |
3 | /*
4 | * Tailrec Function : Recursive Functions
5 | * -> Prevents Stackoverflow Exception
6 | *
7 | * Fibonacci Series
8 | * 0 1 1 2 3 5 8 13 21 ......
9 | * */
10 | fun main(args: Array) {
11 |
12 | println(getFibonacciNumber(10000, BigInteger("1"), BigInteger("0")))
13 | }
14 |
15 | tailrec fun getFibonacciNumber(n: Int, a: BigInteger, b: BigInteger): BigInteger {
16 |
17 | if (n == 0)
18 | return b
19 | else
20 | return getFibonacciNumber(n - 1, a + b, a)
21 | }
22 |
--------------------------------------------------------------------------------
/src/26_class_and_constructor.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Class, Primary Constructor, Secondary Constructor and Init Block
4 | * */
5 | fun main(args: Array) {
6 |
7 | var student = Student("Steve", 10)
8 |
9 | println(student.id)
10 | }
11 |
12 | class Student(var name: String) {
13 |
14 | var id: Int = -1
15 |
16 | init {
17 | println("Student has got a name as $name and id is $id")
18 | }
19 |
20 | constructor(n: String, id: Int): this(n) {
21 | // The body of the secondary constructor is called after init block
22 | this.id = id
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/27_inheritance.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Inheritance
4 | * */
5 | fun main(args: Array) {
6 |
7 | var dog = Dog()
8 | dog.bread = "labra"
9 | dog.color = "black"
10 | dog.bark()
11 | dog.eat()
12 |
13 | var cat = Cat()
14 | cat.age = 7
15 | cat.color = "brown"
16 | cat.meow()
17 | cat.eat()
18 |
19 | var animal = Animal()
20 | animal.color = "white"
21 | animal.eat()
22 | }
23 |
24 | open class Animal { // Super class / Parent class / Base class
25 |
26 | var color: String = ""
27 |
28 | fun eat() {
29 | println("Eat")
30 | }
31 | }
32 |
33 | class Dog : Animal() { // Sub class / Child class / Derived class
34 |
35 | var bread: String = ""
36 |
37 | fun bark() {
38 | println("Bark")
39 | }
40 | }
41 |
42 | class Cat : Animal() { // Sub class / Child class / Derived class
43 |
44 | var age: Int = -1
45 |
46 | fun meow() {
47 | println("Meow")
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/28_overriding_methods_properties.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Method Overriding
4 | * 2. Property Overriding
5 | * */
6 | fun main(args: Array) {
7 |
8 | var dog = MyDog()
9 |
10 | println(dog.color)
11 |
12 | dog.eat()
13 | }
14 |
15 | open class MyAnimal {
16 |
17 | open var color: String = "White"
18 |
19 | open fun eat() {
20 | println("Animal Eating")
21 | }
22 | }
23 |
24 | class MyDog : MyAnimal() {
25 |
26 | var bread: String = ""
27 |
28 | override var color: String = "Black"
29 |
30 | fun bark() {
31 | println("Bark")
32 | }
33 |
34 | override fun eat() {
35 | super.eat()
36 | println("Dog is eating")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/29_inheritance_primary_secondary_constructor.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Inheritance with Primary and Secondary Constructors
4 | * */
5 | fun main(args: Array) {
6 |
7 | var dog = TheDog("Black", "Pug")
8 | }
9 |
10 | open class TheAnimal { // Super class / Parent class / Base class
11 |
12 | var color: String = ""
13 |
14 | constructor(color: String) {
15 | this.color = color
16 | println("From Animal: $color")
17 | }
18 | }
19 |
20 | class TheDog : TheAnimal { // Sub class / Child class / Derived class
21 |
22 | var bread: String = ""
23 |
24 | constructor(color: String, breed: String): super(color) {
25 | this.bread = breed
26 |
27 | println("From Dog: $color and $breed")
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/30_abstract_class.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Abstract Class
4 | * */
5 | fun main(args: Array) {
6 |
7 | // var person = MyPerson() // Not allowed. You cannot create instance of abstract class
8 |
9 | var person = Indian() // Allowed. Abstract Super class reference variable
10 | // pointing to child class object.
11 | person.name = "Steve"
12 | person.eat()
13 | person.goToSchool()
14 | }
15 |
16 | abstract class MyPerson { // you cannot create instance of abstract class
17 |
18 | abstract var name: String
19 |
20 | abstract fun eat() // abstract properties are 'open' by default
21 |
22 | open fun getHeight() {} // A 'open' function ready to be overridden
23 |
24 | fun goToSchool() {} // A normal function
25 | }
26 |
27 | class Indian: MyPerson() {
28 |
29 | override var name: String = "dummy_indian_name"
30 |
31 | override fun eat() {
32 | // Our own code
33 | }
34 | }
--------------------------------------------------------------------------------
/src/31_interface.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * INTERFACE
4 | * */
5 | fun main(args: Array) {
6 |
7 | var myButton = MyButton()
8 | myButton.onTouch()
9 | myButton.onClick()
10 | }
11 |
12 | interface MyInterfaceListener { // You cannot create the instance of interface
13 |
14 | fun onTouch() // Methods in interface are abstract by default
15 |
16 | fun onClick() { // Normal methods are public and open by default but NOT FINAL
17 | println("MyInterfaceListener: onClick")
18 | }
19 | }
20 |
21 | interface MySecondInterface { // You cannot create the instance of interface
22 |
23 | fun onTouch() { // Normal Method
24 | println("MySecondInterface: onTouch")
25 | }
26 |
27 | fun onClick() { // Normal methods are public and open by default but NOT FINAL
28 | println("MySecondInterface: onClick")
29 | }
30 |
31 | }
32 |
33 | class MyButton: MyInterfaceListener, MySecondInterface {
34 |
35 | override fun onTouch() {
36 | super.onClick()
37 | super.onClick()
38 | }
39 |
40 | override fun onClick() {
41 | super.onTouch()
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/32_data_class.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Data Class
4 | * */
5 | fun main(args: Array) {
6 |
7 | var user1 = User("Sam", 10)
8 |
9 | var user2 = User("Sam", 10)
10 |
11 | println(user1.toString())
12 |
13 | if (user1 == user2)
14 | println("Equal")
15 | else
16 | println("Not equal")
17 |
18 | var newUser = user1.copy(id = 25)
19 | println(newUser)
20 | }
21 |
22 | data class User(var name: String, var id: Int)
23 |
--------------------------------------------------------------------------------
/src/33_object_declaration.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Object Declaration
4 | * */
5 | fun main(args: Array) {
6 |
7 | CustomersData.count = 98
8 | CustomersData.typeOfCustomers()
9 |
10 | println(CustomersData.typeOfCustomers())
11 |
12 | CustomersData.count = 109
13 | println(CustomersData.count)
14 |
15 | CustomersData.myMethod("hello")
16 | }
17 |
18 | open class MySuperClass {
19 |
20 | open fun myMethod(str: String) {
21 | println("MySuperClass")
22 | }
23 | }
24 |
25 | object CustomersData: MySuperClass() { // Object Declaration
26 |
27 | var count: Int = -1 // Behaves like a STATIC variable
28 |
29 | fun typeOfCustomers(): String { // Behaves like a STATIC method
30 | return "Indian"
31 | }
32 |
33 | override fun myMethod(str: String) { // Currently, behaving like a STATIC method
34 | super.myMethod(str)
35 | println("object Customer Data: $str")
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/34_1_enum_class:
--------------------------------------------------------------------------------
1 |
2 | interface ICardCashBack {
3 | fun getCashbackValue(): Float
4 | }
5 |
6 | enum class CreditCardType(val color: String, val maxLimit: Int = 1000000): ICardCashBack {
7 | SILVER("gray", 50000) {
8 | override fun getCashbackValue(): Float = 0.02f
9 | },
10 | GOLD("gold"){
11 | override fun getCashbackValue(): Float = 0.04f
12 | },
13 | PLATINUM("black"){
14 | override fun getCashbackValue(): Float = 0.06f
15 | }
16 | }
17 |
18 |
19 | fun main() {
20 |
21 | /* Access properties and methods */
22 | println(CreditCardType.SILVER.color) // gray
23 | println(CreditCardType.SILVER.getCashbackValue()) // 0.02
24 |
25 | /* Enum constants are objects of enum class type. */
26 | val peterCardType: CreditCardType = CreditCardType.GOLD
27 |
28 | /* Each enum object has two properties: ordinal and name */
29 | println(CreditCardType.GOLD.ordinal)
30 | println(CreditCardType.GOLD) // OR CreditCardType.GOLD.name
31 |
32 | /* Each enum object has two methods: values() and valueOf() */
33 | val myConstants: Array = CreditCardType.values()
34 | myConstants.forEach { println(it) }
35 |
36 | /* Using in 'when' statement */
37 | when(peterCardType) {
38 | CreditCardType.SILVER -> println("Peter has silver card")
39 | CreditCardType.GOLD -> println("Peter has gold card")
40 | CreditCardType.PLATINUM -> println("Peter has platinum card")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/34_2_sealed_class.kt:
--------------------------------------------------------------------------------
1 |
2 | // Limitations of Enum class is overcome by sealed class.
3 | enum class Color(val colorShade: String) {
4 | RED("light red"),
5 | GREEN("light green"), // These hard-coded values cannot be changed. They are constants.
6 | // BLUE(val myBlueColorShade: String) // variable values are not allowed in enum
7 | }
8 |
9 | sealed class Shape {
10 | data class Circle(var radius: Float): Shape() // subclass can be a data class
11 | class Square(var side: Int): Shape() // subclass can be a regular class
12 |
13 | object NotAShape : Shape() // subclass can be an object (singleton)
14 |
15 | // sealed class Line : Shape() // subclass can be another sealed class
16 | // sealed interface Draw // subclass can be an interface
17 | }
18 |
19 | // You can define any type of subclass outside the sealed class too
20 | class Rectangle(var length: Int, var breadth: Int): Shape()
21 |
22 |
23 | fun main() {
24 |
25 | var circle = Shape.Circle(3.0f)
26 | var square = Shape.Square(8)
27 | var rectangle = Rectangle(20,10) // Slightly different than above two
28 |
29 | val noShape = Shape.NotAShape
30 |
31 | checkShape(noShape)
32 | }
33 |
34 | fun checkShape(shape: Shape) {
35 |
36 | when (shape) {
37 | is Shape.Circle -> println("Circle area is ${3.14 * shape.radius * shape.radius}")
38 | is Shape.Square -> println("Square area is ${shape.side * shape.side}")
39 | is Rectangle -> println("Rectagle area is ${shape.length * shape.breadth}")
40 | Shape.NotAShape -> println("No shape found") // 'is' is not required for object (singleton)
41 | // else -> "else case is not required as all case is covered above"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/34_companion_object.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Companion Object
4 | * */
5 | fun main(args: Array) {
6 |
7 | MyClass.count // You can print it and check result
8 |
9 | MyClass.typeOfCustomers()
10 | }
11 |
12 | class MyClass {
13 |
14 | companion object {
15 |
16 | var count: Int = -1 // Behaves like STATIC variable
17 |
18 | @JvmStatic
19 | fun typeOfCustomers(): String { // Behaves like STATIC method
20 | return "Indian"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/35_lambdas_higher_order_functions.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | EXAMPLE ONE
4 |
5 | * 1. Lambda Expression
6 | * 2. Higher-Order Function
7 | * */
8 | fun main(args: Array) {
9 |
10 | val program = Program()
11 |
12 | program.addTwoNumbers(2, 7) // Simple way... for better understanding
13 |
14 | program.addTwoNumbers(2, 7, object : MyInterface { // Using Interface / OOPs way
15 |
16 | override fun execute(sum: Int) {
17 | println(sum) // Body
18 | }
19 | })
20 |
21 | val test: String = "Hello"
22 |
23 | val myLambda: (Int) -> Unit = { s: Int -> println(s)} // Lambda Expression [ Function ]
24 | program.addTwoNumbers(2, 7, myLambda)
25 | }
26 |
27 | class Program {
28 |
29 | fun addTwoNumbers(a: Int, b: Int, action: (Int) -> Unit) { // High Level Function with Lambda as Parameter
30 |
31 | val sum = a + b
32 | action(sum) // println(sum)
33 | // println(sum) // Body
34 | }
35 |
36 | fun addTwoNumbers(a: Int, b: Int, action: MyInterface) { // Using Interface / Object Oriented Way
37 | val sum = a + b
38 | action.execute(sum)
39 | }
40 |
41 | fun addTwoNumbers(a: Int, b: Int) { // Simple way.. Just for Better Understanding
42 |
43 | val sum = a + b
44 | println(sum)
45 | }
46 | }
47 |
48 | interface MyInterface {
49 | fun execute(sum: Int)
50 | }
51 |
--------------------------------------------------------------------------------
/src/36_lambdas_example_two.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | EXAMPLE TWO
4 |
5 | * 1. Lambda Expression
6 | * 2. Higher-Order Function
7 | * */
8 | fun main(args: Array) {
9 |
10 | val program = MyProgram()
11 |
12 | // val myLambda: (Int, Int) -> Int = { x, y -> x + y} // Lambda Expression [ Function ]
13 | // OR,
14 | // program.addTwoNumbers(2, 7, { x, y -> x + y })
15 | // OR,
16 | program.addTwoNumbers(2, 7) {x, y -> x + y}
17 | }
18 |
19 | class MyProgram {
20 |
21 | fun addTwoNumbers(a: Int, b: Int, action: (Int, Int) -> Int) { // High Level Function with Lambda as Parameter
22 |
23 | val result = action(a, b)
24 | println(result)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/37_lambdas_closures.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Closures
4 | * */
5 | fun main(args: Array) {
6 |
7 | val program = TheProgram()
8 |
9 | var result = 0
10 |
11 | program.addTwoNumbers(2, 7) {x, y -> result = x + y}
12 |
13 | println(result)
14 | }
15 |
16 | class TheProgram {
17 |
18 | fun addTwoNumbers(a: Int, b: Int, action: (Int, Int) -> Unit) { // High Level Function with Lambda as Parameter
19 |
20 | action(a, b)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/38_it_keyword_lambdas.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * 1. 'it' keyword
5 | * */
6 | fun main(args: Array) {
7 |
8 | val program = Programs()
9 | program.reverseAndDisplay("hello", { it.reversed() })
10 | }
11 |
12 | class Programs {
13 |
14 | fun reverseAndDisplay(str: String, myFunc: (String) -> String) { // High Level Function with Lambda as Parameter
15 |
16 | val result = myFunc(str) // it.reversed() ==> str.reversed() ==> "hello".reversed() = "olleh"
17 | println(result)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/39_with_apply_functions.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. 'with' function
4 | * 2. 'apply' function
5 | * */
6 | fun main(args: Array) {
7 |
8 | var person = Perrson()
9 |
10 | with(person) {
11 | name = "Steve"
12 | age = 23
13 | }
14 |
15 | person.apply {
16 | name = "Steve"
17 | age = 23
18 | }.startRun()
19 |
20 | println(person.name)
21 | println(person.age)
22 | }
23 |
24 | class Perrson {
25 |
26 | var name: String = ""
27 | var age: Int = -1
28 |
29 | fun startRun() {
30 | println("Now I am ready to run")
31 | }
32 | }
--------------------------------------------------------------------------------
/src/40_arrays.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Arrays
4 | * */
5 | fun main(args: Array) {
6 |
7 | // Elements : 32 0 0 54 0
8 | // Index : 0 1 2 3 4
9 |
10 | var myArray = Array(5) { 0 } // Mutable. Fixed Size.
11 | myArray[0] = 32
12 | myArray[3] = 54
13 | myArray[1] = 11
14 |
15 | for (element in myArray) { // Using individual elements (Objects)
16 | println(element)
17 | }
18 |
19 | println()
20 |
21 | for (index in 0..myArray.size - 1) {
22 | println(myArray[index])
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/41_list.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. List and ArrayList
4 | * */
5 | fun main(args: Array) {
6 |
7 | // Elements :
8 | // Index : 0 1 2 3 4
9 |
10 | // var list = mutableListOf() // Mutable, No Fixed Size, Can Add or Remove Elements
11 | // var list = arrayListOf() // Mutable, No Fixed Size, Can Add or Remove Elements
12 | var list = ArrayList() // Mutable, No Fixed Size, Can Add or Remove Elements
13 | list.add("Yogi") // 0
14 | list.add("Manmohan") // 1
15 | list.add("Vajpayee") // 2
16 |
17 | // list.remove("Manmohan")
18 | // list.add("Vajpayee")
19 |
20 | list[1] = "Modi"
21 |
22 | for (element in list) { // Using individual elements (Objects)
23 | println(element)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/42_map_hashmap.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Map and HashMap
4 | * */
5 | fun main(args: Array) {
6 |
7 | // Map Tutorial: Key-Value pair
8 | // var myMap = HashMap() // Mutable, READ and WRITE both, No Fixed Size
9 | // var myMap = mutableMapOf() // Mutable, READ and WRITE both, No Fixed Size
10 | var myMap = hashMapOf() // Mutable, READ and WRITE both, No Fixed Size
11 |
12 | myMap.put(4, "Yogi")
13 | myMap.put(43, "Manmohan")
14 | myMap.put(7, "Vajpayee")
15 |
16 | myMap.put(43, "Modi")
17 |
18 | for (key in myMap.keys) {
19 | println("Element at $key = ${myMap[key]}") // myMap.get(key)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/43_set_hashset.kt:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 1. Set and HashSet
4 | * */
5 | fun main(args: Array) {
6 |
7 | // "Set" contains unique elements
8 | // "HashSet" also contains unique elements but sequence is not guaranteed in output
9 |
10 | var mySet = mutableSetOf( 2, 54, 3, 1, 0, 9, 9, 9, 8) // Mutable Set, READ and WRITE both
11 | // var mySet = hashSetOf( 2, 54, 3, 1, 0, 9, 9, 9, 8) // Mutable Set, READ and WRITE both
12 |
13 | mySet.remove(54)
14 | mySet.add(100)
15 |
16 | for (element in mySet) {
17 | println(element)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/44_filter_map_sorting.kt:
--------------------------------------------------------------------------------
1 | /** FILTER
2 | * Returns a list containing only elements matching the given [predicate]
3 | * */
4 |
5 | /** MAP
6 | * Returns a list containing the results of applying the given [transform] function
7 | * to each element in the original collection
8 | * */
9 |
10 | fun main(args: Array) {
11 |
12 | val myNumbers: List = listOf(2, 3, 4, 6, 23, 90)
13 |
14 | val mySmallNums = myNumbers.filter { it < 10 } // OR { num -> num < 10 }
15 | for (num in mySmallNums) {
16 | println(num)
17 | }
18 |
19 | val mySquaredNums = myNumbers.map { it * it } // OR { num -> num * num }
20 | for (num in mySquaredNums) {
21 | println(num)
22 | }
23 |
24 | var people = listOf(Pperson(10, "Steve"), Pperson(23, "Annie"), Pperson(17, "Sam"))
25 | var names = people.filter { person ->person.name.startsWith("S") }.map { it.name }
26 |
27 | for (name in names) {
28 | println(name)
29 | }
30 | }
31 |
32 | class Pperson(var age: Int, var name: String) {
33 | // Some other code..
34 | }
35 |
--------------------------------------------------------------------------------
/src/45_predicate.kt:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * PREDICATES
4 | * */
5 | fun main(args: Array) {
6 |
7 | val myNumbers = listOf(2, 3, 4, 6, 23, 90)
8 |
9 | val myPredicate = { num: Int -> num > 10 }
10 |
11 | val check1 = myNumbers.all( myPredicate ) // Are all elements greater than 10?
12 | println(check1)
13 |
14 | val check2 = myNumbers.any(myPredicate) // Does any of these elements satisfy the predicate?
15 | println(check2)
16 |
17 | val totalCount: Int = myNumbers.count(myPredicate) // Number of elements that satify the predicate.
18 | println(totalCount)
19 |
20 | val num = myNumbers.find(myPredicate) // Returns the first number that matches the predicate
21 | println(num)
22 | }
23 |
--------------------------------------------------------------------------------
/src/46_null_safety.kt:
--------------------------------------------------------------------------------
1 |
2 | fun main(args: Array) {
3 |
4 | // WAP to find out length of name
5 | val name: String? = "Steve" // change it to null and see the effect in output
6 |
7 | // 1. Safe Call ( ?. )
8 | // Returns the length if 'name' is not null else returns NULL
9 | // Use it if you don't mind getting NULL value
10 | println("The length of name is ${name?.length}")
11 |
12 |
13 | // 2. Safe Call with let ( ?.let )
14 | // It executes the block ONLY IF name is NOT NULL
15 | name?.let {
16 | println("The length of name is ${name.length}")
17 | }
18 |
19 |
20 | // 3. Elvis-operator ( ?: )
21 | // When we have nullable reference 'name', we can say "is name is not null", use it,
22 | // otherwise use some non-null value"
23 | val len = if (name != null)
24 | name.length
25 | else
26 | -1
27 |
28 | val length = name?.length ?: -1
29 | println("The length of name is ${length}")
30 |
31 | // 4. Non-null assertion operator ( !! )
32 | // Use it when you are sure the value is NOT NULL
33 | // Throws NullPointerException if the value is found to be NULL
34 |
35 | println("The length of name is ${name!!.length}")
36 | }
37 |
--------------------------------------------------------------------------------
/src/47_lateinit_keyword.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | fun main(args: Array) {
4 |
5 | val country = Country()
6 |
7 | // country.name = "India"
8 | // println(country.name)
9 |
10 | country.setup()
11 | }
12 |
13 | class Country {
14 |
15 | lateinit var name: String
16 |
17 | fun setup() {
18 | name = "USA"
19 | println("The name of country is $name")
20 | }
21 | }
22 |
23 | // lateinit used only with mutable data type [ var ]
24 | // lateinit used only with non-nullable data type
25 | // lateinit values must be initialised before you use it
26 |
27 | // If you try to access lateinit variable without initializing it then it throws UninitializedPropertyAccessException
28 |
--------------------------------------------------------------------------------
/src/48_lazy_keyword.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | val pi: Float by lazy {
4 | 3.14f
5 | }
6 |
7 | fun main(args: Array) {
8 |
9 | println("Some initial code.....")
10 |
11 | // pi is not initialised yet
12 |
13 | val area1 = pi * 4 * 4 // pi gets initialised and assigned the value of 3.14f for the first time
14 |
15 | val area2 = pi * 9 * 9 // The value pi is loaded from cache memory
16 |
17 | println("Some more code....")
18 | }
19 |
20 |
21 | // ‘lazy initialization’ was designed to prevent unnecessary initialization of objects.
22 | // You variables will not be initialised unless you use it in your code
23 | // It is initialized only once. Next time when you use it, you get the value from cache memory.
24 |
25 | // It is thread safe
26 | // It is initialized in the thread where it is used for the first time.
27 | // Other threads use the same value stored in the cache
28 |
29 | // The variable can be var or val.
30 | // The variable can be nullable or non-nullable
31 |
--------------------------------------------------------------------------------
/src/49_with_scope_function.kt:
--------------------------------------------------------------------------------
1 | class Person {
2 | var name: String = "Sriyank Siddhartha"
3 | var age: Int = 26
4 | }
5 |
6 | fun main() {
7 |
8 | /** Scope Function: 'with'
9 | Property 1: Refer to context object by using 'this'
10 | Property 2: The return value is the 'lambda result' */
11 |
12 | val person = Person()
13 |
14 | val bio: String = with(person) {
15 | println(name)
16 | println(age)
17 | age + 5
18 | "He is a freak who loves to teach in his own way" // will be returned and stored in 'bio' String variable
19 | }
20 |
21 | // println("Age after five years is $ageAfterFiveYears")
22 | println(bio)
23 | }
--------------------------------------------------------------------------------
/src/50_apply_scope_function.kt:
--------------------------------------------------------------------------------
1 | class Person {
2 | var name: String = ""
3 | var age: Int = 0
4 | }
5 |
6 | fun main() {
7 |
8 | /** Scope Function: 'apply'
9 | Property 1: Refer to context object by using 'this'
10 | Property 2: The return value is the 'context object' */
11 |
12 | val person = Person().apply {
13 | name = "Sriyank Siddhartha"
14 | age = 26
15 | }
16 |
17 | with(person) {
18 | println(name) // prints Sriyank Siddhartha
19 | println(age) // prints 26
20 | }
21 |
22 | // Perform some other operations on 'person' object
23 | person.also {
24 | it.name = "Shreks from Smartherd"
25 | println("New name: ${it.name}") // prints New name: Shreks from Smartherd
26 | }
27 | }
--------------------------------------------------------------------------------
/src/51_also_scope_function.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | fun main() {
4 |
5 | /** Scope Function: 'also' 'ALSO PERFORM THE FOLLOWING EXTRA OPERATION'
6 | Property 1: Refer to context object by using 'it'
7 | Property 2: The return value is the 'context object' */
8 |
9 | // Initialise numbersList
10 | val numbersList: MutableList = mutableListOf(1, 2, 3)
11 |
12 | // Some other code... may be a function call or program to swap numbers (doesn't matter what code)
13 |
14 | // Operations on the 'numbersList'
15 | val duplicateNumbers = numbersList.also {
16 | println("The list elements are: $it")
17 | it.add(4)
18 | println("The list elements after adding an element: $it")
19 | it.remove(2)
20 | println("The list elements after removing an element: $it")
21 | }
22 |
23 | // duplicateNumbers will be same as numbersList
24 | println("Original numbers: $numbersList")
25 | println("Duplicate numbers: $duplicateNumbers")
26 | }
--------------------------------------------------------------------------------
/src/52_let_scope_function.kt:
--------------------------------------------------------------------------------
1 |
2 | fun main() {
3 |
4 | /** Scope Function: 'let'
5 | Property 1: Refer to context object by using 'it'
6 | Property 2: The return value is the 'lambda result' */
7 |
8 | // Use 'let' function to avoid NullPointerException
9 |
10 | val name: String? = "Hello"
11 |
12 | // Execute the lambda expression only if the 'name' variable is NOT NULL
13 | val stringLength = name?.let {
14 | println(it.reversed())
15 | println(it.capitalize())
16 | it.length // Will be returned and stored within stringLength variable
17 | }
18 |
19 | println(stringLength)
20 | }
--------------------------------------------------------------------------------
/src/53_run_scope_function.kt:
--------------------------------------------------------------------------------
1 |
2 | class Person {
3 | var name: String = "Sriyank Siddhartha"
4 | var age: Int = 26
5 | }
6 |
7 | fun main() {
8 |
9 | /** Scope Function: 'run'
10 | Property 1: Refer to context object by using 'this'
11 | Property 2: The return value is the 'lambda result' */
12 |
13 | // 'run' is combination of 'with' and 'let'
14 | // If you want to operate on a Nullable object and avoid NullPointerException then use 'run'
15 |
16 | val person: Person? = Person()
17 |
18 | val bio = person?.run {
19 | println(name)
20 | println(age)
21 | age + 5
22 | "He is a freak who loves to teach in his own way" // will be returned and stored in 'bio' variable
23 | }
24 |
25 | println(bio)
26 | }
--------------------------------------------------------------------------------
/src/60_thread_example.kt:
--------------------------------------------------------------------------------
1 | import kotlin.concurrent.thread
2 |
3 | fun main() { // Executes in main thread
4 |
5 | println("Main program starts: ${Thread.currentThread().name}")
6 |
7 | thread { // creates a background thread (worker thread)
8 | println("Fake work starts: ${Thread.currentThread().name}")
9 | Thread.sleep(1000) // Pretend doing some work... may be file upload
10 | println("Fake work finished: ${Thread.currentThread().name}")
11 | }
12 |
13 | println("Main program ends: ${Thread.currentThread().name}")
14 | }
--------------------------------------------------------------------------------
/src/61_first_coroutine.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 |
4 | fun main() { // Executes in main thread
5 |
6 | println("Main program starts: ${Thread.currentThread().name}")
7 |
8 | GlobalScope.launch { // creates a background coroutine that runs on a background thread
9 | println("Fake work starts: ${Thread.currentThread().name}")
10 | Thread.sleep(1000) // Pretend doing some work... may be file upload
11 | println("Fake work finished: ${Thread.currentThread().name}")
12 | }
13 |
14 | // Blocks the current main thread & wait for coroutine to finish (practically not a right way to wait)
15 | Thread.sleep(2000)
16 | println("Main program ends: ${Thread.currentThread().name}")
17 | }
--------------------------------------------------------------------------------
/src/62_runBlocking_and_delay.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 |
4 | fun main() = runBlocking { // Executes in main thread
5 |
6 | println("Main program starts: ${Thread.currentThread().name}") // main thread
7 |
8 | GlobalScope.launch { // Thread: T1
9 | println("Fake work starts: ${Thread.currentThread().name}") // Thread: T1
10 | delay(1000) // Coroutine is suspended but Thread: T1 is free (not blocked)
11 | println("Fake work finished: ${Thread.currentThread().name}") // Either T1 or some other thread.
12 | }
13 |
14 | delay(2000) // main thread: wait for coroutine to finish (practically not a right way to wait)
15 |
16 | println("Main program ends: ${Thread.currentThread().name}") // main thread
17 | }
--------------------------------------------------------------------------------
/src/63_custom_suspending_function.kt:
--------------------------------------------------------------------------------
1 |
2 | import kotlinx.coroutines.*
3 |
4 |
5 | fun main() = runBlocking { // Executes in main thread
6 |
7 | println("Main program starts: ${Thread.currentThread().name}") // main thread
8 |
9 | GlobalScope.launch { // Thread: T1
10 | println("Fake work starts: ${Thread.currentThread().name}") // Thread: T1
11 | mySuspendFunc(1000) // Coroutine is suspended but Thread: T1 is free (not blocked)
12 | println("Fake work finished: ${Thread.currentThread().name}") // Either T1 or some other thread.
13 | }
14 |
15 | mySuspendFunc(2000) // main thread: wait for coroutine to finish (practically not a right way to wait)
16 |
17 | println("Main program ends: ${Thread.currentThread().name}") // main thread
18 | }
19 |
20 | suspend fun mySuspendFunc(time: Long) {
21 | // code..
22 | delay(time)
23 | }
--------------------------------------------------------------------------------
/src/64_launch_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 |
4 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
5 |
6 | println("Main program starts: ${Thread.currentThread().name}") // main thread
7 |
8 | val job: Job = launch { // Thread: main
9 | println("Fake work starts: ${Thread.currentThread().name}") // Thread: main
10 | delay(1000) // Coroutine is suspended but Thread: main is free (not blocked)
11 | println("Fake work finished: ${Thread.currentThread().name}") // Thread: main
12 | }
13 |
14 | job.join() // main thread: wait for coroutine to finish
15 |
16 | println("Main program ends: ${Thread.currentThread().name}") // main thread
17 | }
--------------------------------------------------------------------------------
/src/65_async_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 |
4 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
5 |
6 | println("Main program starts: ${Thread.currentThread().name}") // main thread
7 |
8 | val deferredJob: Deferred = async // Thread: main
9 | println("Fake work starts: ${Thread.currentThread().name}") // Thread: main
10 | delay(1000) // Coroutine is suspended but Thread: main is free (not blocked)
11 | println("Fake work finished: ${Thread.currentThread().name}") // Thread: main
12 | 15
13 | }
14 |
15 | val num: Int = deferredJob.await() // main thread: wait for coroutine to finish and return data
16 |
17 | println("Main program ends: ${Thread.currentThread().name}") // main thread
18 | }
--------------------------------------------------------------------------------
/src/66_a_runBlocking_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 |
4 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
5 |
6 | println("Main program starts: ${Thread.currentThread().name}") // main thread
7 |
8 | val deferredJob: Deferred = async // Thread: main
9 | println("Fake work starts: ${Thread.currentThread().name}") // Thread: main
10 | delay(1000) // Coroutine is suspended but Thread: main is free (not blocked)
11 | println("Fake work finished: ${Thread.currentThread().name}") // Thread: main
12 | 15
13 | }
14 |
15 | val num: Int = deferredJob.await() // main thread: wait for coroutine to finish and return data
16 |
17 | println("Main program ends: ${Thread.currentThread().name}") // main thread
18 | }
19 |
20 | suspend fun myOwnSuspendingFunc() {
21 | delay(1000) // do something
22 | }
--------------------------------------------------------------------------------
/src/66_b_test_case.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.runBlocking
2 | import org.junit.Assert
3 | import org.junit.Test
4 |
5 | class SimpleTest {
6 |
7 | @Test
8 | fun myFirstTest() = runBlocking {
9 | myOwnSuspendingFunc()
10 | Assert.assertEquals(10, 5 + 5)
11 | }
12 | }
--------------------------------------------------------------------------------
/src/68_cooperative_coroutine_suspend_function.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | val job: Job = launch { // Thread main: Creates a non-blocking coroutine
8 | for (i in 0..500) {
9 | print("$i.")
10 | yield() // or use delay() or any other suspending function as per your need.
11 | }
12 | }
13 |
14 | delay(10) // Let's print a few values before we cancel
15 | job.cancelAndJoin()
16 |
17 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
18 | }
19 |
--------------------------------------------------------------------------------
/src/69_isActive_flag_cooperative_coroutine.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | val job: Job = launch(Dispatchers.Default) { // Thread T1: Creates a non-blocking coroutine
8 | for (i in 0..500) {
9 | if (!isActive) {
10 | return@launch // break
11 | }
12 | print("$i.")
13 | Thread.sleep(1)
14 | }
15 | }
16 |
17 | delay(10) // Let's print a few values before we cancel
18 | job.cancelAndJoin()
19 |
20 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
21 | }
--------------------------------------------------------------------------------
/src/70_exception_handling.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | val job: Job = launch(Dispatchers.Default) { // Thread T1: Creates a non-blocking coroutine
8 | try {
9 | for (i in 0..500) {
10 | print("$i.")
11 | delay(5) // or use yield() or any other suspending function as per your need.
12 | }
13 | } catch (ex: CancellationException) {
14 | print("\nException caught safely: ${ex.message}")
15 | } finally {
16 | print("\nClose resources in finally")
17 | }
18 | }
19 |
20 | delay(10) // Let's print a few values before we cancel
21 | job.cancel(CancellationException("My own crash message"))
22 | job.join()
23 |
24 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
25 | }
--------------------------------------------------------------------------------
/src/71_withContext_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | val job: Job = launch(Dispatchers.Default) { // Thread T1: Creates a non-blocking coroutine
8 | try {
9 | for (i in 0..500) {
10 | print("$i.")
11 | delay(5) // or use yield() or any other suspending function as per your need.
12 | }
13 | } catch (ex: CancellationException) {
14 | print("\nException caught safely: ${ex.message}")
15 | } finally {
16 | withContext(NonCancellable) {
17 | delay(1000) // Generally we don't use suspending function in finally
18 | print("\nClose resources in finally")
19 | }
20 | }
21 | }
22 |
23 | delay(10) // Let's print a few values before we cancel
24 | job.cancel(CancellationException("My own crash message"))
25 | job.join()
26 |
27 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
28 | }
--------------------------------------------------------------------------------
/src/72_withTimeout_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | withTimeout(1300) {
8 | try {
9 | for (i in 0..1000) {
10 | print("$i.")
11 | delay(500)
12 | }
13 | } catch (ex: TimeoutCancellationException) {
14 | // .. code..
15 | } finally {
16 | // .. code..
17 | }
18 | }
19 |
20 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
21 | }
--------------------------------------------------------------------------------
/src/73_withTimeoutOrNull_coroutine_builder.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
4 |
5 | println("Main program starts: ${Thread.currentThread().name}") // main thread
6 |
7 | val result: String? = withTimeoutOrNull(2000) {
8 | for (i in 0..500) {
9 | print("$i.")
10 | delay(500)
11 | }
12 |
13 | "I am done"
14 | }
15 |
16 | print("Result: $result")
17 |
18 | println("\nMain program ends: ${Thread.currentThread().name}") // main thread
19 | }
--------------------------------------------------------------------------------
/src/74_sequential_suspending_functions.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 | import kotlin.system.measureTimeMillis
3 |
4 |
5 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
6 |
7 | println("Main program starts: ${Thread.currentThread().name}") // main thread
8 |
9 | val time = measureTimeMillis {
10 | val msgOne = getMessageOne()
11 | val msgTwo = getMessageTwo()
12 | println("The entire message is: ${msgOne + msgTwo}")
13 | }
14 |
15 | println("Completed in $time ms")
16 | println("Main program ends: ${Thread.currentThread().name}") // main thread
17 | }
18 |
19 | suspend fun getMessageOne(): String {
20 | delay(1000L) // pretend to do some work
21 | return "Hello "
22 | }
23 |
24 | suspend fun getMessageTwo(): String {
25 | delay(1000L) // pretend to do some work
26 | return "World!"
27 | }
--------------------------------------------------------------------------------
/src/75_concurrency_within_coroutine.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 | import kotlin.system.measureTimeMillis
3 |
4 |
5 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
6 |
7 | println("Main program starts: ${Thread.currentThread().name}") // main thread
8 |
9 | val time = measureTimeMillis {
10 | val msgOne: Deferred = async {
11 | // ..more code..
12 | getMessageOne()
13 | }
14 | val msgTwo: Deferred = async {
15 | // ..more code..
16 | getMessageTwo()
17 | }
18 | println("The entire message is: ${msgOne.await() + msgTwo.await()}")
19 | }
20 |
21 | println("Completed in $time ms")
22 | println("Main program ends: ${Thread.currentThread().name}") // main thread
23 | }
24 |
25 | suspend fun getMessageOne(): String {
26 | delay(1000L) // pretend to do some work
27 | return "Hello "
28 | }
29 |
30 | suspend fun getMessageTwo(): String {
31 | delay(1000L) // pretend to do some work
32 | return "World!"
33 | }
--------------------------------------------------------------------------------
/src/76_lazy_async.kt:
--------------------------------------------------------------------------------
1 |
2 | import kotlinx.coroutines.*
3 |
4 | fun main() = runBlocking { // Creates a blocking coroutine that executes in current thread (main)
5 |
6 | println("Main program starts: ${Thread.currentThread().name}") // main thread
7 |
8 | val msgOne: Deferred = async(start = CoroutineStart.LAZY) { getMessageOne() }
9 | val msgTwo: Deferred = async(start = CoroutineStart.LAZY) { getMessageTwo() }
10 | println("The entire message is: ${msgOne.await() + msgTwo.await()}")
11 |
12 | println("Main program ends: ${Thread.currentThread().name}") // main thread
13 | }
14 |
15 | suspend fun getMessageOne(): String {
16 | delay(1000L) // pretend to do some work
17 | println("After working in getMessageOne()")
18 | return "Hello "
19 | }
20 |
21 | suspend fun getMessageTwo(): String {
22 | delay(1000L) // pretend to do some work
23 | println("After working in getMessageTwo()")
24 | return "World!"
25 | }
--------------------------------------------------------------------------------
/src/77_CoroutineScope.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking {
4 |
5 | println("runBlocking: $this")
6 |
7 | launch {
8 | println("launch: $this")
9 |
10 | launch(coroutineContext) {
11 | println("child launch: $this")
12 | }
13 | }
14 |
15 | async {
16 | println("async: $this")
17 | }
18 |
19 | println("... some other code...")
20 | }
--------------------------------------------------------------------------------
/src/78_CoroutineContext_and_Dispatchers.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 |
3 | fun main() = runBlocking {
4 |
5 | // this: CoroutineScope instance
6 | // coroutineContext: CoroutineContext instance
7 |
8 | /* Without Parameter: CONFINED [CONFINED DISPATCHER]
9 | - Inherits CoroutineContext from immediate parent coroutine.
10 | - Even after delay() or suspending function, it continues to run in the same thread. */
11 | launch {
12 | println("C1: ${Thread.currentThread().name}") // Thread: main
13 | delay(1000)
14 | println("C1 after delay: ${Thread.currentThread().name}") // Thread: main
15 | }
16 |
17 | /* With parameter: Dispatchers.Default [similar to GlobalScope.launch { } ]
18 | - Gets its own context at Global level. Executes in a separate background thread.
19 | - After delay() or suspending function execution,
20 | it continues to run either in the same thread or some other thread. */
21 | launch(Dispatchers.Default) {
22 | println("C2: ${Thread.currentThread().name}") // Thread: T1
23 | delay(1000)
24 | println("C2 after delay: ${Thread.currentThread().name}") // Thread: Either T1 or some other thread
25 | }
26 |
27 | /* With parameter: Dispatchers.Unconfined [UNCONFINED DISPATCHER]
28 | - Inherits CoroutineContext from the immediate parent coroutine.
29 | - After delay() or suspending function execution, it continues to run in some other thread. */
30 | launch(Dispatchers.Unconfined) {
31 | println("C3: ${Thread.currentThread().name}") // Thread: main
32 | delay(1000)
33 | println("C3 after delay: ${Thread.currentThread().name}") // Thread: some other thread T1
34 | }
35 |
36 | launch(coroutineContext) {
37 | println("C4: ${Thread.currentThread().name}") // Thread: main
38 | delay(1000)
39 | println("C4 after delay: ${Thread.currentThread().name}") // Thread: main
40 | }
41 |
42 | println("...Main Program...")
43 | }
44 |
--------------------------------------------------------------------------------
/src/MyJavaFile.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * Interoperability Example
5 | * */
6 | public class MyJavaFile {
7 |
8 | public static void main(String[] args) {
9 |
10 | int sum = MyKotlinInteroperabilityKt.addNumbers(3, 4);
11 | System.out.println("Printing sum from Java file :" + sum);
12 | }
13 |
14 | public static int getArea(int l, int b) {
15 | return l * b;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/myKotlinInteroperability.kt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | * Interoperability Example
5 | * */
6 | fun main(args: Array) {
7 |
8 | var area = MyJavaFile.getArea(10, 5)
9 | println("Printing area from Kotlin file: $area")
10 | }
11 |
12 | fun addNumbers(a: Int, b: Int): Int {
13 | return a + b
14 | }
15 |
--------------------------------------------------------------------------------