├── .gitignore ├── README.md ├── examples ├── build.gradle └── src │ ├── _0J2K │ ├── JPerson.java │ ├── KPerson.kt │ ├── UsingFromJava.java │ └── UsingFromKotlin.kt │ ├── _10Sequences │ └── SequencesExample.kt │ ├── _11LambdasWithReceiver │ ├── LambdaVsLambdaWithReceiver.kt │ ├── UsefulFunctions.kt │ └── buildString.kt │ ├── _12Conventions │ ├── Conventions.kt │ └── Point.kt │ ├── _13DelegatedProperties │ ├── LazyProperty.kt │ └── Observable.kt │ ├── _14Reified │ ├── _0TypeErasure.kt │ ├── _1Reified.kt │ ├── _2FilterIsInstance.kt │ ├── _3ClassReferences.kt │ ├── _4Validators.kt │ └── _5RestrictionsOnReifiedTypeParameters.kt │ ├── _15DSLs │ ├── HtmlExample.kt │ └── HtmlExampleStart.kt │ ├── _16Variance │ ├── collectionExample.kt │ └── functionExample.kt │ ├── _1Intro │ ├── UsingFoo.java │ ├── _0Main.kt │ ├── _1Variables.kt │ └── _2Functions.kt │ ├── _2ControlStructures │ ├── _1IfAndWhen.kt │ ├── _2Loops.kt │ ├── _3Iterating.kt │ └── _4Ranges.kt │ ├── _3Extensions │ ├── Extensions.kt │ └── ExtensionsFromJava.java │ ├── _4Classes │ ├── _10InnerClass.kt │ ├── _11ClassDelegation.kt │ ├── _1Classes.kt │ ├── _2PrimaryConstructor.kt │ ├── _3Constructors.kt │ ├── _4Properties.kt │ ├── _5MutableProperty.kt │ ├── _6ReadOnlyProperty.kt │ ├── _7Equals.kt │ ├── _8DataClass.kt │ ├── _9SealedClass.kt │ └── javaCode │ │ ├── Person.java │ │ └── Rectangle.java │ ├── _5Objects │ ├── JSingleton.java │ ├── UsingCompanionObjectFromJava.java │ ├── UsingKotlinObjectFromJava.java │ ├── _1Object.kt │ └── _2CompanionObject.kt │ ├── _6Nullability │ ├── ChainCalls.kt │ ├── Nullability.kt │ ├── NullableTypes.java │ └── Safecast.kt │ ├── _7TypeSystem │ ├── MutableVsReadonly.kt │ ├── NPEinPureKotlin.kt │ ├── NullableTypes.kt │ ├── PlatformTypes.kt │ ├── Session.java │ ├── UsingUnitFromJava.java │ ├── WhyReadOnly.kt │ ├── basicTypes.kt │ ├── example.kt │ ├── nothing.kt │ └── unit.kt │ ├── _8Lambdas │ ├── Capture.kt │ ├── DestructuringInLambdas.kt │ ├── Intro.kt │ ├── Labels.kt │ ├── Lambdas.kt │ ├── MemberReferences.kt │ ├── MultilineLambda.kt │ ├── UsingFunctionTypesFromJava.java │ ├── WorkingWithCollections.kt │ └── WorkingWithStrings.kt │ └── _9InlineFunctions │ ├── _0SynchronizedFunction.kt │ ├── _1RunFunction.kt │ ├── _2LetFunction.kt │ ├── _3TakeIfAndTakeUnlessFunctions.kt │ └── _4RepeatFunction.kt ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── tasks ├── build.gradle └── src ├── _1Intro ├── _1IntroTasks.kt └── _2Foo.kt ├── _2Extensions ├── Extensions.kt ├── MemberVsExtension.kt ├── ParentVsChild.kt ├── ParentVsChildJava.java ├── RepeatExample.kt └── UsingRepeatFromJava.java ├── _3Classes ├── Evaluation.kt ├── Foo.kt ├── InnerAndNested.kt ├── Person.kt ├── UsePersonFromJava.java └── Visibility.kt ├── _4Nullability ├── Lists.kt ├── Name.kt ├── SafeCasts.kt └── isNullOrEmpty.kt ├── _5TypeSystem ├── JavaClass.java ├── Parent.java ├── Subclass.java ├── Usage.java ├── _1NPE.kt ├── _2ExplicitTypeSpecification.kt ├── _2NullInList.kt └── _3NPEDuringInitialization.kt ├── _6Lambdas └── Heroes.kt └── _7InlineAndLazyIteration ├── Inline.kt ├── IntermediateCollections.kt └── LazyIteration.kt /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | kotlin-workshop.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Kotlin workshop materials 2 | 3 | Additional materials (presentations and questions) can be found at https://github.com/jetBrains/kotlin-workshop. 4 | -------------------------------------------------------------------------------- /examples/build.gradle: -------------------------------------------------------------------------------- 1 | group 'kotlin-workshop' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.1.51' 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | } 13 | } 14 | 15 | apply plugin: 'java' 16 | apply plugin: 'kotlin' 17 | 18 | sourceCompatibility = 1.5 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 26 | compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" 27 | testCompile group: 'junit', name: 'junit', version: '4.12' 28 | } 29 | 30 | sourceSets { 31 | main.kotlin.srcDirs += 'src' 32 | test.kotlin.srcDirs += 'test' 33 | } -------------------------------------------------------------------------------- /examples/src/_0J2K/JPerson.java: -------------------------------------------------------------------------------- 1 | package _0J2K; 2 | 3 | public class JPerson { 4 | private final String name; 5 | private int age; 6 | 7 | public JPerson(String name, int age) { 8 | this.name = name; 9 | this.age = age; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public int getAge() { 17 | return age; 18 | } 19 | 20 | public void setAge(int age) { 21 | this.age = age; 22 | } 23 | } -------------------------------------------------------------------------------- /examples/src/_0J2K/KPerson.kt: -------------------------------------------------------------------------------- 1 | package _0J2K 2 | 3 | class KPerson(val name: String, var age: Int) -------------------------------------------------------------------------------- /examples/src/_0J2K/UsingFromJava.java: -------------------------------------------------------------------------------- 1 | package _0J2K; 2 | 3 | public class UsingFromJava { 4 | public static void main(String[] args) { 5 | JPerson jPerson = new JPerson("Alice", 29); 6 | jPerson.getName(); 7 | jPerson.setAge(jPerson.getAge() + 1); 8 | 9 | KPerson kPerson = new KPerson("Alice", 29); 10 | kPerson.getName(); 11 | kPerson.setAge(kPerson.getAge() + 1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/src/_0J2K/UsingFromKotlin.kt: -------------------------------------------------------------------------------- 1 | package _0J2K 2 | 3 | fun main(args: Array) { 4 | val jPerson = JPerson("Alice", 29) 5 | jPerson.name 6 | jPerson.age = jPerson.age + 1 7 | 8 | val kPerson = KPerson("Alice", 29) 9 | kPerson.name 10 | kPerson.age++ 11 | } -------------------------------------------------------------------------------- /examples/src/_10Sequences/SequencesExample.kt: -------------------------------------------------------------------------------- 1 | package _10Sequences 2 | 3 | fun main(args: Array) { 4 | val sequence = listOf(1, 2, 3).asSequence() 5 | for (i in sequence) { } 6 | 7 | val numbers = generateSequence(0) { it + 1 } 8 | println(numbers.take(5).toList()) 9 | } -------------------------------------------------------------------------------- /examples/src/_11LambdasWithReceiver/LambdaVsLambdaWithReceiver.kt: -------------------------------------------------------------------------------- 1 | package _11LambdasWithReceiver 2 | 3 | fun String.lastChar() = 4 | this.get(this.length - 1) 5 | 6 | fun main(args: Array) { 7 | buildString { 8 | this.append("...") 9 | } 10 | 11 | val isEven: (Int) -> Boolean = { it % 2 == 0 } 12 | val isOdd: Int.() -> Boolean = { this % 2 == 1 } 13 | 14 | isEven(0) 15 | 1.isOdd() 16 | 17 | println(isEven(0)) 18 | println(1.isOdd()) 19 | } 20 | 21 | inline fun buildString( 22 | builderAction: StringBuilder.() -> Unit 23 | ): String { 24 | val stringBuilder = StringBuilder() 25 | stringBuilder.builderAction(); 26 | return stringBuilder.toString() 27 | } -------------------------------------------------------------------------------- /examples/src/_11LambdasWithReceiver/UsefulFunctions.kt: -------------------------------------------------------------------------------- 1 | package _11LambdasWithReceiver 2 | 3 | class BreakfastMenuItem { 4 | var name: String? = null 5 | var price: Double? = null 6 | var calories: Int? = null 7 | } 8 | 9 | fun initializeMenuItem(): BreakfastMenuItem { 10 | val menuItem = BreakfastMenuItem() 11 | menuItem.name = "Belgian Waffles" 12 | menuItem.price = 5.95 13 | menuItem.calories = 650 14 | return menuItem 15 | } 16 | 17 | fun initializeMenuItem1(): BreakfastMenuItem { 18 | val menuItem = BreakfastMenuItem() 19 | with(menuItem) { 20 | name = "Belgian Waffles" 21 | price = 5.95 22 | calories = 650 23 | } 24 | return menuItem 25 | 26 | } 27 | 28 | fun initializeMenuItem2(): BreakfastMenuItem = 29 | BreakfastMenuItem().apply { 30 | name = "Belgian Waffles" 31 | price = 5.95 32 | calories = 650 33 | } 34 | 35 | fun initializeMenuItem3(): BreakfastMenuItem = 36 | BreakfastMenuItem().also { 37 | it.name = "Belgian Waffles" 38 | it.price = 5.95 39 | it.calories = 650 40 | } -------------------------------------------------------------------------------- /examples/src/_11LambdasWithReceiver/buildString.kt: -------------------------------------------------------------------------------- 1 | package _11LambdasWithReceiver 2 | 3 | fun main(args: Array) { 4 | println(useWith()) 5 | println(useApply()) 6 | println(useAlso()) 7 | } 8 | 9 | fun useWith() = with(StringBuilder()) { 10 | appendln("Alphabet: ") 11 | for (c in 'a'..'z') { 12 | append(c) 13 | } 14 | toString() 15 | } 16 | 17 | fun useApply() = StringBuilder().apply { 18 | appendln("Alphabet: ") 19 | for (c in 'a'..'z') { 20 | append(c) 21 | } 22 | }.toString() 23 | 24 | fun useAlso(): String = StringBuilder().also { 25 | it.appendln("Alphabet: ") 26 | for (c in 'a'..'z') { 27 | it.append(c) 28 | } 29 | }.toString() -------------------------------------------------------------------------------- /examples/src/_12Conventions/Conventions.kt: -------------------------------------------------------------------------------- 1 | package _12Conventions 2 | 3 | fun main(args: Array) { 4 | val list = listOf(1, 2, 3) 5 | println(list + 4) // [1, 2, 3, 4] 6 | println(list.plus(4)) // [1, 2, 3, 4] 7 | println(list - 2) // [1, 3] 8 | 9 | val mutableList = mutableListOf(1, 2, 3) 10 | mutableList += 4 // [1, 2, 3, 4] 11 | 12 | val s1 = "abc" 13 | val s2 = "def" 14 | s1 < s2 // s1.compareTo(s2) < 0 15 | s1 > s2 16 | s1 <= s2 17 | s1 >= s2 18 | 19 | val map = mutableMapOf(1 to "one", 2 to "two") 20 | val key = 3 21 | val value = "three" 22 | map[key] // operator get 23 | map[key] = value // operator set 24 | 25 | println(map[3]) 26 | 27 | println(3 in map) 28 | 29 | 1..2 30 | "abc".."def" 31 | 32 | for (i in 1..2) { } 33 | for (ch in "abc") { } 34 | "abc".iterator() 35 | 36 | // for (s in "abc".."def") { } - doesn't make sense 37 | 38 | val (i, s) = 1 to "s" 39 | val pair = 1 to "s" 40 | val ii = pair.component1() 41 | val ss = pair.component2() 42 | 43 | val (iii, sss) = Foo(1, "") 44 | } 45 | 46 | data class Foo(val i: Int, val s: String) -------------------------------------------------------------------------------- /examples/src/_12Conventions/Point.kt: -------------------------------------------------------------------------------- 1 | package _12Conventions 2 | 3 | data class Point(val x: Int, val y: Int) 4 | 5 | operator fun Point.plus(other: Point): Point { 6 | return Point(x + other.x, y + other.y) 7 | } 8 | 9 | operator fun Point.times(scale: Int): Point { 10 | return Point(x * scale, y * scale) 11 | } 12 | 13 | fun main(args: Array) { 14 | val p1 = Point(1, 2) + Point(2, 3) 15 | val p2 = Point(1, 2) * 3 16 | println(p1) 17 | println(p2) 18 | } -------------------------------------------------------------------------------- /examples/src/_13DelegatedProperties/LazyProperty.kt: -------------------------------------------------------------------------------- 1 | package _13DelegatedProperties 2 | 3 | class LazyProperty { 4 | val lazy: Int by lazy { 5 | println("Calculate the value") 6 | 42 7 | } 8 | } 9 | 10 | fun main(args: Array) { 11 | println("--- creation ---") 12 | val property = LazyProperty() 13 | 14 | println("--- first access ---") 15 | property.lazy 16 | 17 | println("--- second access ---") 18 | property.lazy 19 | } -------------------------------------------------------------------------------- /examples/src/_13DelegatedProperties/Observable.kt: -------------------------------------------------------------------------------- 1 | package _13DelegatedProperties 2 | 3 | import kotlin.properties.Delegates 4 | import kotlin.reflect.KProperty 5 | 6 | class Person( 7 | val name: String, age: Int, salary: Int 8 | ) { 9 | private val observer = { 10 | prop: KProperty<*>, oldValue: Int, newValue: Int -> 11 | println("Property value $oldValue has changed to $newValue") 12 | } 13 | var age: Int by Delegates.observable(age, observer) 14 | var salary: Int by Delegates.observable(salary, observer) 15 | } 16 | 17 | fun main(args: Array) { 18 | val person = Person("Alice", 25, 2000) 19 | person.age++ 20 | person.salary += 100 21 | } -------------------------------------------------------------------------------- /examples/src/_14Reified/_0TypeErasure.kt: -------------------------------------------------------------------------------- 1 | package _14Reified.typeErasure 2 | 3 | // Erasure of Generic Types 4 | 5 | // Erasure of Generic Methods 6 | 7 | class Node(val data: T, val next: Node) 8 | 9 | /* 10 | public final class Node { 11 | 12 | private final Ljava/lang/Object; data 13 | 14 | public final getData()Ljava/lang/Object; 15 | 16 | private final LNode; next 17 | 18 | public final getNext()LNode; 19 | 20 | public (Ljava/lang/Object;LNode;)V 21 | } 22 | 23 | */ 24 | 25 | fun foo(t: T) {} 26 | fun > bar(t: T) {} 27 | 28 | /* 29 | public final static foo(Ljava/lang/Object;)V 30 | 31 | public final static bar(Ljava/lang/Comparable;)V 32 | */ 33 | -------------------------------------------------------------------------------- /examples/src/_14Reified/_1Reified.kt: -------------------------------------------------------------------------------- 1 | package _14Reified 2 | 3 | inline fun isA(value: Any) = value is T 4 | 5 | fun main(args: Array) { 6 | println(isA("abc")) 7 | println(isA(123)) 8 | } -------------------------------------------------------------------------------- /examples/src/_14Reified/_2FilterIsInstance.kt: -------------------------------------------------------------------------------- 1 | package _14Reified 2 | 3 | fun main(args: Array) { 4 | val anys: List = 5 | listOf(1, "one", 2.0) 6 | 7 | val strings: List = 8 | anys.filterIsInstance() 9 | /* 10 | The code generated by the compiler 11 | instead of calling inline function 'filterIsInstance': 12 | val destination = mutableListOf() 13 | for (element in this) { 14 | if (element is String) { 15 | destination.add(element) 16 | } 17 | } 18 | val strings = destination 19 | */ 20 | 21 | println(strings) 22 | } 23 | 24 | inline fun 25 | Iterable<*>.filterIsInstance(): List { 26 | 27 | val destination = mutableListOf() 28 | for (element in this) { 29 | if (element is T) { 30 | destination.add(element) 31 | } 32 | } 33 | return destination 34 | } -------------------------------------------------------------------------------- /examples/src/_14Reified/_3ClassReferences.kt: -------------------------------------------------------------------------------- 1 | package _14Reified 2 | 3 | import java.util.* 4 | 5 | class Service 6 | 7 | fun main(args: Array) { 8 | 9 | ServiceLoader.load(Service::class.java) 10 | 11 | loadService() 12 | } 13 | 14 | inline fun loadService() = 15 | ServiceLoader.load(T::class.java) 16 | -------------------------------------------------------------------------------- /examples/src/_14Reified/_4Validators.kt: -------------------------------------------------------------------------------- 1 | package reifiedGenerics 2 | 3 | import kotlin.reflect.KClass 4 | 5 | interface FieldValidator { 6 | fun validate(input: T): Boolean 7 | } 8 | 9 | object Validators { 10 | private val validators = mutableMapOf, FieldValidator<*>>() 11 | 12 | fun registerValidator( 13 | kClass: KClass, fieldValidator: FieldValidator) { 14 | validators[kClass] = fieldValidator 15 | } 16 | 17 | @Suppress("UNCHECKED_CAST") 18 | operator fun get(kClass: KClass): FieldValidator? = 19 | validators[kClass] as FieldValidator? 20 | } 21 | 22 | 23 | object DefaultStringValidator : FieldValidator { 24 | override fun validate(input: String) = input.isNotEmpty() 25 | } 26 | 27 | object DefaultIntValidator : FieldValidator { 28 | override fun validate(input: Int) = input >= 0 29 | } 30 | 31 | fun main(args: Array) { 32 | Validators.registerValidator(String::class, DefaultStringValidator) 33 | Validators.registerValidator(Int::class, DefaultIntValidator) 34 | 35 | println(Validators[String::class]?.validate("Kotlin")) 36 | println(Validators[Int::class]?.validate(42)) 37 | } -------------------------------------------------------------------------------- /examples/src/_14Reified/_5RestrictionsOnReifiedTypeParameters.kt: -------------------------------------------------------------------------------- 1 | package _14Reified 2 | 3 | // Which of the following calls won't compile? 4 | 5 | inline fun foo(t: T) { 6 | // bar(t) 7 | } 8 | 9 | fun bar(t: T) { 10 | // foo(t) 11 | } -------------------------------------------------------------------------------- /examples/src/_15DSLs/HtmlExample.kt: -------------------------------------------------------------------------------- 1 | package _15DSLs 2 | 3 | @DslMarker 4 | annotation class HtmlDsl 5 | 6 | open class Tag(val name: String) { 7 | private val children = mutableListOf() 8 | 9 | protected fun doInit(child: T, init: T.() -> Unit) { 10 | child.init() 11 | children.add(child) 12 | } 13 | 14 | override fun toString() = 15 | "<$name>${children.joinToString("")}" 16 | } 17 | 18 | fun table(init: TABLE.() -> Unit): TABLE { 19 | val table = TABLE() 20 | table.init() 21 | return table 22 | } 23 | 24 | @HtmlDsl 25 | class TABLE : Tag("table") { 26 | fun tr(init: TR.() -> Unit) = doInit(TR(), init) 27 | } 28 | 29 | @HtmlDsl 30 | class TR : Tag("tr") { 31 | fun td(init: TD.() -> Unit) = doInit(TD(), init) 32 | } 33 | 34 | @HtmlDsl 35 | class TD : Tag("td") 36 | 37 | fun createTable(): TABLE { 38 | return table { 39 | tr { 40 | for (i in 1..2) { 41 | td { 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | fun main(args: Array) { 49 | println(createTable()) 50 | //
51 | } -------------------------------------------------------------------------------- /examples/src/_15DSLs/HtmlExampleStart.kt: -------------------------------------------------------------------------------- 1 | package _15DSLs2 2 | 3 | 4 | open class Tag(val name: String) { 5 | protected val children = mutableListOf() 6 | 7 | override fun toString() = 8 | "<$name>${children.joinToString("")}" 9 | } 10 | 11 | fun table(init: TABLE.() -> Unit): TABLE = TABLE() 12 | 13 | class TABLE : Tag("table") 14 | 15 | fun createTable(): TABLE { 16 | return table { 17 | /* 18 | tr { 19 | for (i in 1..2) { 20 | td { 21 | } 22 | } 23 | } 24 | */ 25 | } 26 | } 27 | 28 | fun main(args: Array) { 29 | println(createTable()) 30 | //
31 | } -------------------------------------------------------------------------------- /examples/src/_16Variance/collectionExample.kt: -------------------------------------------------------------------------------- 1 | package _16Variance 2 | 3 | fun main(args: Array) { 4 | val strings = mutableListOf("abc", "cde") 5 | @Suppress("UNCHECKED_CAST") 6 | doSomethingWithList(strings as MutableList) 7 | 8 | for (string in strings) { 9 | 10 | } 11 | } 12 | 13 | fun doSomethingWithList(list: MutableList) { 14 | list.add(1) 15 | } 16 | 17 | interface MyMutableList { 18 | fun get(): T 19 | // fun add(t: T) 20 | } 21 | -------------------------------------------------------------------------------- /examples/src/_16Variance/functionExample.kt: -------------------------------------------------------------------------------- 1 | package _16Variance 2 | 3 | val animalsCache = mutableMapOf() 4 | val catsCache = mutableMapOf() 5 | 6 | open class Animal 7 | class Cat: Animal() 8 | class Dog: Animal() 9 | 10 | fun universalNumbering(animal: Animal): Int = animalsCache.getOrPut(animal) { animalsCache.size + 1 } 11 | fun catsNumbering(cat: Cat): Int = catsCache.getOrPut(cat) { catsCache.size + 1 } 12 | 13 | fun main(args: Array) { 14 | enumerateCats(::universalNumbering) 15 | // enumerateAnimals(::catsNumbering) 16 | } 17 | 18 | fun enumerateCats(f: (Cat) -> Int) { 19 | f(Cat()) 20 | } 21 | 22 | fun enumerateAnimals(f: (Any) -> Int) { 23 | f(Cat()) 24 | f(Dog()) 25 | } 26 | 27 | interface MyFunction { 28 | fun invoke(p: P): R 29 | } -------------------------------------------------------------------------------- /examples/src/_1Intro/UsingFoo.java: -------------------------------------------------------------------------------- 1 | package _1Intro; 2 | 3 | public class UsingFoo { 4 | public static void main(String[] args) { 5 | // _0MainKt.foo(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/src/_1Intro/_0Main.kt: -------------------------------------------------------------------------------- 1 | package _1Intro 2 | 3 | fun main(args: Array) { 4 | val name = if (args.size > 0) args[0] else "Kotlin" 5 | println("Hello, $name!") 6 | 7 | // ${} 8 | } 9 | -------------------------------------------------------------------------------- /examples/src/_1Intro/_1Variables.kt: -------------------------------------------------------------------------------- 1 | package _1Intro 2 | 3 | fun main(args: Array) { 4 | // read-only 5 | val question: String = 6 | "life, the universe, " + 7 | "and everything" 8 | println("$question?") 9 | 10 | // mutable 11 | var answer = 0 12 | answer = 42 13 | println(answer) 14 | 15 | // answer = "no answer" 16 | 17 | // val is read-only reference, not object 18 | val languages = mutableListOf("Java") 19 | languages.add("Kotlin") 20 | } -------------------------------------------------------------------------------- /examples/src/_1Intro/_2Functions.kt: -------------------------------------------------------------------------------- 1 | package _1Intro 2 | 3 | fun max(a: Int, b: Int): Int { 4 | return if (a < b) a else b 5 | } 6 | 7 | fun max2(a: Int, b: Int) = if (a < b) a else b 8 | 9 | // default values for arguments 10 | fun sum(a: Int, b: Int, c: Int = 0) = a + b + c 11 | 12 | fun use() { 13 | sum(1, 2) 14 | sum(1, 2, 3) 15 | // named arguments 16 | sum(b = 2, a = 1) 17 | } -------------------------------------------------------------------------------- /examples/src/_2ControlStructures/_1IfAndWhen.kt: -------------------------------------------------------------------------------- 1 | package whenAsExpression 2 | 3 | import whenAsExpression.Color.* 4 | 5 | enum class Color { 6 | BLUE, ORANGE, RED 7 | } 8 | 9 | fun getDescription(color: Color) = 10 | when (color) { 11 | BLUE -> "cold" 12 | ORANGE -> "mild" 13 | RED -> "hot" 14 | } 15 | 16 | fun whenSyntax(a: Any) = when (a) { 17 | 0 -> "is zero" 18 | is Int -> "is integer" 19 | is String -> "is string of length ${a.length}" 20 | else -> "other" 21 | } 22 | 23 | fun updateWeather( 24 | celsiusDegrees: Double 25 | ) { 26 | val description: String 27 | val color: Color 28 | when { 29 | celsiusDegrees < 0 -> { 30 | description = "cold" 31 | color = BLUE 32 | } 33 | celsiusDegrees in 0..15 -> { 34 | description = "mild" 35 | color = ORANGE 36 | } 37 | else -> { 38 | description = "hot" 39 | color = RED 40 | } 41 | } 42 | } 43 | 44 | fun updateWeather1(celsiusDegrees: Double) { 45 | val (description, color) = 46 | when { 47 | celsiusDegrees < 0 -> Pair("cold", BLUE) 48 | celsiusDegrees in 0..15 -> "mild" to ORANGE 49 | else -> "hot" to RED 50 | } 51 | } -------------------------------------------------------------------------------- /examples/src/_2ControlStructures/_2Loops.kt: -------------------------------------------------------------------------------- 1 | package loops 2 | 3 | fun whileLoop() { 4 | fun condition() = true 5 | 6 | while (condition()) { 7 | /*...​*/ 8 | } 9 | 10 | do { 11 | /*...​*/ 12 | } while (condition()) 13 | } 14 | 15 | 16 | fun forLoop() { 17 | val list = listOf(1, 2, 3) 18 | for (element in list) { 19 | print(element) 20 | } 21 | 22 | for (i in 1..9) { // including 9 23 | print(i) 24 | } 25 | 26 | // excluding 10 (the same as 1..9) 27 | for (i in 1 until 10) { 28 | print(i) 29 | } 30 | 31 | for (i in 9 downTo 1 step 2) { 32 | print(i) 33 | } 34 | } 35 | 36 | fun main(args: Array) { 37 | forLoop() 38 | } -------------------------------------------------------------------------------- /examples/src/_2ControlStructures/_3Iterating.kt: -------------------------------------------------------------------------------- 1 | package iterating 2 | 3 | fun iteratingOverCollection() { 4 | val list = listOf("a", "b") 5 | for (s in list) { 6 | println(s) 7 | } 8 | } 9 | 10 | fun iteratingOverMap() { 11 | val map = mapOf(1 to "one", 2 to "two", 3 to "three") 12 | 13 | for ((key, value) in map) { 14 | println("$key = $value") 15 | } 16 | } 17 | 18 | fun iteratingOverCollectionWithIndex() { 19 | for ((index, element) in listOf("a", "b", "c").withIndex()) { 20 | println("$index $element") 21 | } 22 | } 23 | 24 | fun main(args: Array) { 25 | iteratingOverCollection() 26 | iteratingOverMap() 27 | iteratingOverCollectionWithIndex() 28 | } -------------------------------------------------------------------------------- /examples/src/_2ControlStructures/_4Ranges.kt: -------------------------------------------------------------------------------- 1 | package ranges 2 | 3 | fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z' 4 | // c in 'a'..'z' 5 | // is compiled to: 6 | // 'a' <= c && c <= 'z' 7 | 8 | fun isNotDigit(c: Char) = c !in '0'..'9' 9 | 10 | fun main(args: Array) { 11 | "abc" <= "cba" 12 | "abc".compareTo("cba") 13 | 14 | println(isLetter('q')) // true 15 | println(isNotDigit('x')) // true 16 | } 17 | 18 | fun recognize(c: Char) = when (c) { 19 | in '0'..'9' -> "It's a digit!" 20 | in 'a'..'z', in 'A'..'Z' -> "It's a letter!" 21 | else -> "I don't know…​" 22 | } 23 | 24 | fun rangeOfStrings() { 25 | val fromAToK = "a".."k" 26 | println("ball" in fromAToK) // true 27 | println("zoo" in fromAToK) // false 28 | } -------------------------------------------------------------------------------- /examples/src/_3Extensions/Extensions.kt: -------------------------------------------------------------------------------- 1 | //@file:JvmName("StringUtil") 2 | package _3Extensions 3 | 4 | fun String.lastChar() = 5 | this.get(this.length - 1) 6 | 7 | // 'this' can be omitted 8 | fun String.lastChar1() = 9 | get(length - 1) 10 | 11 | fun test() { 12 | // visible in completion 13 | "abc".lastChar() 14 | } -------------------------------------------------------------------------------- /examples/src/_3Extensions/ExtensionsFromJava.java: -------------------------------------------------------------------------------- 1 | package _3Extensions; 2 | 3 | import static _3Extensions.ExtensionsKt.lastChar; 4 | 5 | public class ExtensionsFromJava { 6 | public static void main(String[] args) { 7 | char ch = lastChar("abc"); 8 | 9 | // char ch = StringUtil.lastChar("abc"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/src/_4Classes/_10InnerClass.kt: -------------------------------------------------------------------------------- 1 | package innerClasses 2 | 3 | import innerClasses.A.B 4 | 5 | class A { 6 | class B { 7 | fun foo() { 8 | println("B") 9 | println(this) 10 | // doesn't compile: 11 | // println(this@A) 12 | } 13 | } 14 | 15 | inner class C { 16 | fun foo() { 17 | println("C") 18 | println(this) 19 | println(this@A) 20 | } 21 | } 22 | } 23 | 24 | fun main(args: Array) { 25 | val a = A() 26 | val b = B() 27 | val c = a.C() 28 | b.foo() 29 | c.foo() 30 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_11ClassDelegation.kt: -------------------------------------------------------------------------------- 1 | package _4Classes 2 | 3 | class Customer 4 | 5 | interface Repository { 6 | fun getById(id: Int): Customer 7 | fun getAll(): List 8 | } 9 | 10 | interface Logger { 11 | fun logAll() 12 | } 13 | 14 | class Controller( 15 | repository: Repository, 16 | logger: Logger 17 | ) : Repository by repository, Logger by logger 18 | 19 | fun use(controller: Controller) { 20 | controller.logAll() 21 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_1Classes.kt: -------------------------------------------------------------------------------- 1 | package classes 2 | 3 | // similar to javaCode.Person 4 | 5 | data class Person(val name: String, val age: Int) 6 | 7 | fun main(args: Array) { 8 | // no new keyword, constructor is called as a regular function 9 | val person = Person("Alice", 26) 10 | 11 | println(person.name) 12 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_2PrimaryConstructor.kt: -------------------------------------------------------------------------------- 1 | package primaryConstructor 2 | 3 | /* short syntax */ 4 | class Person1(val name: String) 5 | 6 | /* full syntax */ 7 | // constructor parameter 8 | class Person2(name: String) { 9 | 10 | // property 11 | val name: String 12 | 13 | // constructor body 14 | init { 15 | this.name = name 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/src/_4Classes/_3Constructors.kt: -------------------------------------------------------------------------------- 1 | package constructors 2 | 3 | class Rectangle(val height: Int, val width: Int) { 4 | 5 | //secondary constructors 6 | constructor(side: Int) : this(side, side) 7 | } 8 | 9 | fun main(args: Array) { 10 | val rectangle = Rectangle(42) 11 | println(rectangle.height == rectangle.width) 12 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_4Properties.kt: -------------------------------------------------------------------------------- 1 | package properties 2 | 3 | class Rectangle(val height: Int, val width: Int) { 4 | 5 | // you can redefine getter (and setter) 6 | val isSquare: Boolean 7 | get() { 8 | return height == width 9 | } 10 | } 11 | 12 | fun main(args: Array) { 13 | val rectangle = Rectangle(41, 43) 14 | println(rectangle.isSquare) 15 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_5MutableProperty.kt: -------------------------------------------------------------------------------- 1 | package _4Classes 2 | 3 | class LengthCounter { 4 | var counter: Int = 0 5 | private set 6 | 7 | fun addWord(word: String) { 8 | counter += word.length 9 | } 10 | } 11 | 12 | fun main(args: Array) { 13 | val lengthCounter = LengthCounter() 14 | lengthCounter.addWord("Hi!") 15 | println(lengthCounter.counter) 16 | 17 | StateLogger().state = true 18 | } 19 | 20 | class StateLogger { 21 | var state = false 22 | set(value) { 23 | println("state has changed") 24 | field = value 25 | } 26 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_6ReadOnlyProperty.kt: -------------------------------------------------------------------------------- 1 | package _4Classes 2 | 3 | import java.util.* 4 | 5 | val foo: Int 6 | get() = Random().nextInt() 7 | 8 | fun main(args: Array) { 9 | println(foo) 10 | println(foo) 11 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_7Equals.kt: -------------------------------------------------------------------------------- 1 | package equals 2 | 3 | fun main(args: Array) { 4 | val set1 = setOf(1, 2, 3) 5 | val set2 = setOf(1, 2, 3) 6 | 7 | // checks reference equality 8 | println(set1 === set2) 9 | 10 | // calls equals 11 | println(set1 == set2) 12 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_8DataClass.kt: -------------------------------------------------------------------------------- 1 | package dataClasses 2 | 3 | // Adding data makes the compiler generate useful methods 4 | // such as equals, hashCode, toString, copy. 5 | data class Contact(val name: String, var address: String) 6 | 7 | fun main(args: Array) { 8 | val contact = Contact("Harry Potter", "4 Privet Drive") 9 | val contact2 = Contact("Harry Potter", "4 Privet Drive") 10 | println(contact) 11 | println(contact == contact2) 12 | 13 | contact.copy(address = "Hogwarts") 14 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/_9SealedClass.kt: -------------------------------------------------------------------------------- 1 | package sealedClasses 2 | 3 | sealed class Expr 4 | class Num(val value: Int) : Expr() 5 | class Sum(val left: Expr, val right: Expr) : Expr() 6 | 7 | fun eval(e: Expr): Int = when (e) { 8 | is Num -> e.value 9 | is Sum -> eval(e.left) + eval(e.right) 10 | } 11 | 12 | fun main(args: Array) { 13 | // 1 + (2 + 3) 14 | println(eval(Sum(Num(1), Sum(Num(2), Num(3))))) 15 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/javaCode/Person.java: -------------------------------------------------------------------------------- 1 | package _4Classes.javaCode; 2 | 3 | public class Person { 4 | private final String name; 5 | private final int age; 6 | 7 | public Person(String name, int age) { 8 | this.name = name; 9 | this.age = age; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public int getAge() { 17 | return age; 18 | } 19 | } -------------------------------------------------------------------------------- /examples/src/_4Classes/javaCode/Rectangle.java: -------------------------------------------------------------------------------- 1 | package _4Classes.javaCode; 2 | 3 | public class Rectangle { 4 | private final int width; 5 | private final int height; 6 | 7 | public Rectangle(int width, int height) { 8 | this.width = width; 9 | this.height = height; 10 | } 11 | 12 | public int getWidth() { 13 | return width; 14 | } 15 | 16 | public int getHeight() { 17 | return height; 18 | } 19 | 20 | public boolean isSquare() { 21 | return width == height; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/src/_5Objects/JSingleton.java: -------------------------------------------------------------------------------- 1 | package _5Objects; 2 | 3 | public class JSingleton { 4 | public final static JSingleton INSTANCE = new JSingleton(); 5 | 6 | private JSingleton() { 7 | } 8 | 9 | public void foo() {} 10 | } 11 | -------------------------------------------------------------------------------- /examples/src/_5Objects/UsingCompanionObjectFromJava.java: -------------------------------------------------------------------------------- 1 | package _5Objects; 2 | 3 | public class UsingCompanionObjectFromJava { 4 | 5 | public static void main(String[] args) { 6 | 7 | A.Companion.create(); 8 | // A.create() //- doesn't compile 9 | 10 | B.Companion.staticFunction(); 11 | B.staticFunction(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/src/_5Objects/UsingKotlinObjectFromJava.java: -------------------------------------------------------------------------------- 1 | package _5Objects; 2 | 3 | public class UsingKotlinObjectFromJava { 4 | public static void main(String[] args) { 5 | JSingleton.INSTANCE.foo(); 6 | KSingleton.INSTANCE.foo(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/src/_5Objects/_1Object.kt: -------------------------------------------------------------------------------- 1 | package _5Objects 2 | 3 | object KSingleton { 4 | fun foo() {} 5 | } 6 | 7 | fun main(args: Array) { 8 | KSingleton.foo() 9 | } -------------------------------------------------------------------------------- /examples/src/_5Objects/_2CompanionObject.kt: -------------------------------------------------------------------------------- 1 | package _5Objects 2 | 3 | interface Factory { 4 | fun create(): T 5 | } 6 | 7 | // Companion object can implement an interface 8 | class A { 9 | private constructor() 10 | 11 | companion object : Factory { 12 | override fun create(): A { 13 | return A() 14 | } 15 | } 16 | } 17 | 18 | class B { 19 | companion object { 20 | // use annotation to make a member static 21 | @JvmStatic 22 | fun staticFunction() {} 23 | } 24 | } -------------------------------------------------------------------------------- /examples/src/_6Nullability/ChainCalls.kt: -------------------------------------------------------------------------------- 1 | package _6Nullability 2 | 3 | fun sendMessageToClient( 4 | client: Client?, message: String?, mailer: Mailer 5 | ){ 6 | val email = client?.personalInfo?.email 7 | 8 | if (email != null && message != null) { 9 | mailer.sendMessage(email, message) 10 | } 11 | 12 | } 13 | 14 | class Client (val personalInfo: PersonalInfo?) 15 | class PersonalInfo (val email: String?) 16 | interface Mailer { 17 | fun sendMessage(email: String, message: String) 18 | } -------------------------------------------------------------------------------- /examples/src/_6Nullability/Nullability.kt: -------------------------------------------------------------------------------- 1 | package _6Nullability 2 | 3 | fun main(args: Array) { 4 | 5 | val s1: String = "always not null" 6 | val s2: String? = null 7 | 8 | val i1: Int = s1.length 9 | // s2.length 10 | 11 | if (s2 != null) s2.length 12 | s2?.length 13 | 14 | val i2: Int? = if (s2 != null) s2.length else null 15 | val i3: Int? = s2?.length 16 | 17 | val i4: Int? = if (s2 != null) s2.length else 0 18 | val i5: Int = s2?.length ?: 0 19 | 20 | s2!! 21 | } 22 | 23 | fun test1(s: String?) { 24 | if (s == null) return 25 | s.length 26 | } 27 | 28 | fun test2(s: String?) { 29 | if (s == null) fail() 30 | s.length 31 | } 32 | 33 | fun test3(s: String?) { 34 | val i: Int = s?.length ?: fail() 35 | } 36 | 37 | fun fail(): Nothing = 38 | throw UnsupportedOperationException() -------------------------------------------------------------------------------- /examples/src/_6Nullability/NullableTypes.java: -------------------------------------------------------------------------------- 1 | package _6Nullability; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | public class NullableTypes { 7 | public void sendMessageToClient( 8 | @Nullable Client client, 9 | @Nullable String message, 10 | @NotNull Mailer mailer 11 | ) { 12 | if (client == null || message == null) return; 13 | 14 | PersonalInfo personalInfo = client.getPersonalInfo(); 15 | if (personalInfo == null) return; 16 | 17 | String email = personalInfo.getEmail(); 18 | if (email == null) return; 19 | 20 | mailer.sendMessage(email, message); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/src/_6Nullability/Safecast.kt: -------------------------------------------------------------------------------- 1 | package _6Nullability 2 | 3 | class A(val value: Int) 4 | 5 | fun foo(a: Any?) = (a as? A)?.value 6 | 7 | fun main(args: Array) { 8 | println(foo(A(42))) // 42 9 | println(foo(42)) // null 10 | println(foo(null)) // null 11 | } 12 | 13 | fun test(a: Any) { 14 | val s = if (a is String) a else null 15 | // ... 16 | } -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/MutableVsReadonly.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | fun main(args: Array) { 4 | val mutableList = mutableListOf(1, 2, 3) 5 | val list: List = mutableList 6 | 7 | println(list) // [1, 2, 3] 8 | mutableList.add(4) 9 | println(list) // [1, 2, 3, 4] 10 | } -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/NPEinPureKotlin.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | class A { 4 | val foo: String 5 | init { 6 | foo = "" 7 | } 8 | 9 | private fun initialize() { 10 | println(foo.length) 11 | } 12 | } 13 | 14 | fun main(args: Array) { 15 | val a = A() 16 | } -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/NullableTypes.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | fun test() { 4 | val session = Session() 5 | val description: String = session.description 6 | println(description) 7 | } 8 | 9 | fun foo(s: String) {} -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/PlatformTypes.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | fun main(args: Array) { 4 | explicitNullableType() 5 | explicitNotNullType() 6 | noExplicitType() 7 | } 8 | 9 | fun noExplicitType() { 10 | val session = Session() 11 | val description = session.description 12 | println(description.length) // NPE 13 | } 14 | 15 | fun explicitNotNullType() { 16 | val session = Session() 17 | val description: String = session.description // IllegalStateException 18 | println(description.length) 19 | 20 | } 21 | 22 | fun explicitNullableType() { 23 | val session = Session() 24 | val description: String? = session.description // ok 25 | println(description?.length) // null 26 | } -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/Session.java: -------------------------------------------------------------------------------- 1 | package _7TypeSystem; 2 | 3 | public class Session { 4 | public String getDescription() { 5 | return null; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/UsingUnitFromJava.java: -------------------------------------------------------------------------------- 1 | package _7TypeSystem; 2 | 3 | import kotlin.Unit; 4 | 5 | public class UsingUnitFromJava implements Processor { 6 | public Unit process() { 7 | // In Java you still have to return a value explicitly: 8 | return Unit.INSTANCE; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/WhyReadOnly.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | class Customer 4 | object Shop { 5 | private val customers = mutableListOf() 6 | fun getCustomers(): List = TODO() 7 | } 8 | 9 | fun usage() { 10 | val customers = Shop.getCustomers() 11 | // customers.add() 12 | } 13 | -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/basicTypes.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | // Call "Show Kotlin Bytecode" action. 4 | // You may call "Decompile" to look at the corresponding Java code. 5 | 6 | // int getInt(); 7 | fun getInt(): Int = 1 8 | 9 | // java.lang.Integer getNullableInt(); 10 | fun getNullableInt(): Int? = null 11 | 12 | // java.util.List getListOfInts(); 13 | fun getListOfInts(): List = listOf(1, 2, 3) 14 | 15 | // String[] getArray(); 16 | fun getArray(): Array = arrayOf("ab", "cd") 17 | 18 | // java.lang.Object getAny(); 19 | fun getAny(): Any = 1 20 | 21 | // java.lang.String getString(); 22 | fun getString(): String = "" -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/example.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | fun foo(): Int = 1 4 | 5 | fun bar(): Int? = 2 -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/nothing.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | import classes.Person 4 | 5 | fun greetPerson(person: Person) { 6 | val name = person.name 7 | ?: throw IllegalArgumentException("Name is unspecified") 8 | println("Hello, $name!") 9 | } 10 | 11 | fun checkTypes(condition: Boolean, expression: Int) { 12 | val result: Int = if (condition) { 13 | expression 14 | } else { 15 | fail("error") 16 | } 17 | } 18 | 19 | fun fail(message: String): Nothing = throw UnsupportedOperationException(message) 20 | 21 | fun example2() { 22 | val answer: Int = if (timeHasPassed()) { 23 | 42 24 | } else { 25 | fail("Something went wrong") 26 | } 27 | } 28 | 29 | fun example3() { 30 | val answer: Int = if (timeHasPassed()) { 31 | 42 32 | } else { 33 | TODO("Something needs to be done") 34 | } 35 | } 36 | 37 | fun timeHasPassed(): Boolean { 38 | return false 39 | } 40 | 41 | fun nullableNothing() { 42 | val n: Nothing? = null 43 | } 44 | 45 | fun foo1(): List = listOf(null) 46 | -------------------------------------------------------------------------------- /examples/src/_7TypeSystem/unit.kt: -------------------------------------------------------------------------------- 1 | package _7TypeSystem 2 | 3 | fun f(): Unit {} 4 | 5 | fun g() {} 6 | 7 | interface Processor { 8 | fun process(): T 9 | } 10 | 11 | class NoResultProcessor : Processor { 12 | override fun process() { 13 | // do stuff 14 | } 15 | } 16 | 17 | fun main(args: Array) { 18 | // This type has only one value 'Unit': 19 | val u: Unit = Unit 20 | println(u) // kotlin.Unit 21 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/Capture.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas 2 | 3 | fun main(args: Array) { 4 | 5 | val increment = 1 6 | var sum = 0 7 | 8 | val inc = { 9 | println(increment) 10 | sum += increment 11 | } 12 | 13 | inc() 14 | inc() 15 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/DestructuringInLambdas.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas 2 | 3 | fun main(args: Array) { 4 | val map = mapOf(1 to "one", 2 to "two") 5 | map.mapValues { (key, value) -> "$key -> $value!" } 6 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/Intro.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas 2 | 3 | fun main(args: Array) { 4 | val list = listOf(1, 8, 33, 42) 5 | 6 | // only even numbers 7 | val even = mutableListOf() 8 | for (i in list) { 9 | if (i % 2 == 0) { 10 | even += i 11 | } 12 | } 13 | 14 | // only numbers > 10 15 | val moreThan10 = mutableListOf() 16 | for (i in list) { 17 | if (i > 10) { 18 | moreThan10 += i 19 | } 20 | } 21 | 22 | println(even) 23 | println(moreThan10) 24 | 25 | println(list.filter { it % 2 == 0 }) 26 | println(list.filter { it > 10 }) 27 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/Labels.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas 2 | 3 | data class Person(val name: String, val age: Int) 4 | 5 | fun lookForAlice(people: List) { 6 | people.forEach { 7 | if (it.name == "Alice") return@forEach 8 | } 9 | println("Alice might be somewhere") 10 | } 11 | 12 | fun lookForAlice1(people: List) { 13 | people.filter(fun (person): Boolean { 14 | if (person.name == "Alice") return true 15 | println("${person.name} is not Alice") 16 | return false 17 | }) 18 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/Lambdas.kt: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | fun basicSyntax() { 4 | val sum = { x: Int, y: Int -> x + y } 5 | 6 | val sum1: (Int, Int) -> Int = { x, y -> x + y } 7 | 8 | val multilineLambda = { x: Int, y: Int -> 9 | println("Computing...") 10 | x + y 11 | } 12 | 13 | println(sum(1, 2)) // 3 14 | } 15 | 16 | fun shortSyntax() { 17 | val string = "one, two, three" 18 | 19 | val isLowercaseChar: (Char) -> Boolean = { c: Char -> c in 'a'..'z' } 20 | println(string.filter(isLowercaseChar)) // "onetwothree" 21 | 22 | println(string.filter({ c: Char -> c in 'a'..'z' })) // "onetwothree" 23 | 24 | string.filter() { c: Char -> c in 'a'..'z' } 25 | 26 | string.filter { c: Char -> c in 'a'..'z' } 27 | 28 | string.filter { c -> c in 'a'..'z' } 29 | 30 | string.filter { it in 'a'..'z' } 31 | } 32 | 33 | fun main(args: Array) { 34 | basicSyntax() 35 | shortSyntax() 36 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/MemberReferences.kt: -------------------------------------------------------------------------------- 1 | package memberReference 2 | 3 | class Person(val name: String, val age: Int) 4 | 5 | fun main(args: Array) { 6 | val people = listOf( 7 | Person("Alice", 29), 8 | Person("Bob", 31)) 9 | 10 | people.maxBy { it.age } 11 | 12 | people.maxBy(Person::age) 13 | 14 | val list = listOf(1, 2, 3, 4) 15 | 16 | list.any(::isEven) 17 | 18 | list.filter(::isEven) 19 | } 20 | 21 | fun isEven(i: Int): Boolean = i % 2 == 0 22 | -------------------------------------------------------------------------------- /examples/src/_8Lambdas/MultilineLambda.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas 2 | 3 | fun main(args: Array) { 4 | val list = listOf(1, 2, 3) 5 | list.any { 6 | println("processing $it") 7 | it > 0 8 | } 9 | } -------------------------------------------------------------------------------- /examples/src/_8Lambdas/UsingFunctionTypesFromJava.java: -------------------------------------------------------------------------------- 1 | package _8Lambdas; 2 | 3 | import kotlin.collections.CollectionsKt; 4 | import kotlin.jvm.functions.Function1; 5 | 6 | import java.util.List; 7 | 8 | public class UsingFunctionTypesFromJava { 9 | public static void useKotlinLibrary() { 10 | List list = CollectionsKt.listOf(1, 2, 3); 11 | boolean hasEven = CollectionsKt.any(list, 12 | new Function1() { 13 | public Boolean invoke(Integer i) { 14 | return i % 2 == 0; 15 | } 16 | }); 17 | System.out.println(hasEven); 18 | } 19 | 20 | public static void main(String[] args) { 21 | useKotlinLibrary(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/src/_8Lambdas/WorkingWithCollections.kt: -------------------------------------------------------------------------------- 1 | package _8Lambdas.workingWithCollections 2 | 3 | data class Person(val name: String, val age: Int) 4 | 5 | fun main(args: Array) { 6 | val people = listOf( 7 | Person("Alice", 31), 8 | Person("Bob", 29), 9 | Person("Carol", 31)) 10 | 11 | println(people.filter { it.age > 30 }) 12 | println(people.map { it.name }) 13 | 14 | println(people.maxBy { it.age }) 15 | 16 | println(people.any { it.name.startsWith("A") }) 17 | 18 | println(people.find { it.age > 30 }) 19 | println(people.firstOrNull { it.age > 30 }) 20 | 21 | val (even, odd) = listOf(1, 2, 3, 4).partition { it % 2 == 0 } 22 | println(even) 23 | println(odd) 24 | 25 | "abCDa".zip("79371").joinToString() 26 | 27 | println(people.groupBy { it.age }) 28 | println(people.associateBy { it.name }) 29 | println(people.associateBy { it.age }) 30 | 31 | println(listOf("abc", "123").map { 32 | it.toCharArray().toList() }) 33 | 34 | println(listOf("abc", "123").flatMap { 35 | it.toCharArray().toList() }) 36 | } 37 | -------------------------------------------------------------------------------- /examples/src/_8Lambdas/WorkingWithStrings.kt: -------------------------------------------------------------------------------- 1 | package libraryFunctions 2 | 3 | // filter, count, 4 | // any, all, none, find 5 | // withIndex, zip 6 | // (map, flatMap, maxBy, partition) 7 | 8 | fun main(args: Array) { 9 | val s = "abCDa" 10 | 11 | println(s.filter { it in 'a'..'z' }) // aba 12 | println(s.count { it in 'a'..'z' }) //3 13 | 14 | "abCDa".any { it in '1'..'9' } // false 15 | "abCDa1".any { it in '1'..'9' } // true 16 | // true if there at least one character satisfying the predicate 17 | 18 | "abCDa".all { it.toInt() < 200 } 19 | "abd33".find { it > 'c' } // d 20 | 21 | for ((index, ch) in "abc".withIndex()) { 22 | 23 | } 24 | 25 | println("abcd".zip("1234")) 26 | 27 | "abCDa".any { it in 'a'..'z' } 28 | "abCDa".count { it in 'a'..'z' } 29 | "abCDa".find { it in 'a'..'z' } 30 | "abCDa".zip("79371").joinToString() 31 | } -------------------------------------------------------------------------------- /examples/src/_9InlineFunctions/_0SynchronizedFunction.kt: -------------------------------------------------------------------------------- 1 | package _9InlineFunctions 2 | 3 | import java.util.concurrent.locks.Lock 4 | import java.util.concurrent.locks.ReentrantLock 5 | import kotlin.concurrent.withLock 6 | 7 | inline fun synchronized(lock: Lock, action: () -> T): T { 8 | lock.lock() 9 | try { 10 | return action() 11 | } finally { 12 | lock.unlock() 13 | } 14 | } 15 | 16 | fun foo(lock: Lock) { 17 | synchronized(lock) { 18 | println("Action") 19 | } 20 | } 21 | 22 | fun __foo__(lock: Lock) { 23 | lock.lock() 24 | try { 25 | println("Action") 26 | } finally { 27 | lock.unlock() 28 | } 29 | } 30 | 31 | fun main(args: Array) { 32 | 33 | val l = ReentrantLock() 34 | 35 | synchronized(l) { 36 | // ... 37 | } 38 | 39 | l.withLock { 40 | // ... 41 | } 42 | } -------------------------------------------------------------------------------- /examples/src/_9InlineFunctions/_1RunFunction.kt: -------------------------------------------------------------------------------- 1 | package _9InlineFunctions 2 | 3 | val foo = run { 4 | println("Calculating foo...") 5 | "foo" 6 | } 7 | 8 | fun main(args: Array) { 9 | println(foo) 10 | } -------------------------------------------------------------------------------- /examples/src/_9InlineFunctions/_2LetFunction.kt: -------------------------------------------------------------------------------- 1 | package _9InlineFunctions 2 | 3 | fun sendEmailTo(email: String) { /*...*/ } 4 | 5 | fun example(email: String?) { 6 | 7 | if (email != null) sendEmailTo(email) 8 | email?.let { e -> sendEmailTo(e) } 9 | 10 | val e = getEmail() 11 | if (e != null) sendEmailTo(e) 12 | 13 | getEmail()?.let { sendEmailTo(it) } 14 | } 15 | 16 | inline fun T.let(block: (T) -> R): R = block(this) 17 | 18 | fun getEmail(): String? = null -------------------------------------------------------------------------------- /examples/src/_9InlineFunctions/_3TakeIfAndTakeUnlessFunctions.kt: -------------------------------------------------------------------------------- 1 | package _9InlineFunctions 2 | 3 | data class Contract(val info: String, val isSigned: Boolean) 4 | 5 | fun main(args: Array) { 6 | val contract1 = Contract("Kotlin training", true) 7 | println(contract1.takeIf { it.isSigned }) // contract1 8 | 9 | val contract2 = Contract("Other training", false) 10 | println(contract2.takeIf { it.isSigned }) // null 11 | 12 | val number = 42 13 | println(number.takeIf { it > 10 }) // 42 14 | 15 | val other = 2 16 | println(other.takeIf { it > 10 }) // null 17 | 18 | println(contract1.takeUnless { it.isSigned }) // null 19 | 20 | println(contract2.takeUnless { it.isSigned }) // contract2 21 | 22 | println(number.takeUnless { it > 10 }) // null 23 | 24 | println(other.takeUnless { it > 10 }) // 2 25 | } -------------------------------------------------------------------------------- /examples/src/_9InlineFunctions/_4RepeatFunction.kt: -------------------------------------------------------------------------------- 1 | package _9InlineFunctions 2 | 3 | fun main(args: Array) { 4 | repeat(10) { 5 | println("Welcome!") 6 | } 7 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svtk/kotlin-workshop/ac42b006fbaae219df7adf33478735d9463e2672/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 12 11:52:11 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-rc-2-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'kotlin-workshop' 2 | include 'examples' 3 | include 'tasks' 4 | 5 | -------------------------------------------------------------------------------- /tasks/build.gradle: -------------------------------------------------------------------------------- 1 | group 'kotlin-workshop' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.1.4-2' 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | } 13 | } 14 | 15 | apply plugin: 'java' 16 | apply plugin: 'kotlin' 17 | 18 | sourceCompatibility = 1.5 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 26 | compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" 27 | testCompile group: 'junit', name: 'junit', version: '4.12' 28 | } 29 | 30 | sourceSets { 31 | main.kotlin.srcDirs += 'src' 32 | test.kotlin.srcDirs += 'test' 33 | } -------------------------------------------------------------------------------- /tasks/src/_1Intro/_1IntroTasks.kt: -------------------------------------------------------------------------------- 1 | package questions.i_intro 2 | 3 | fun main(args: Array) { 4 | var string = 1 5 | // the variable string has type Int 6 | // string = "a" 7 | 8 | val languages = listOf("Java") 9 | // list is read-only 10 | // languages.add("Kotlin") 11 | 12 | println(listOf('a', 'b', 'c').joinToString( 13 | separator = "", prefix = "(", postfix = ")")) 14 | // (abc) 15 | 16 | println("Kotlin" in "Java".."Scala") // true 17 | // "Java" <= "Kotlin" && "Kotlin" <= "Scala" 18 | 19 | println("Kotlin" in setOf("Java", "Scala")) // false 20 | 21 | val list = mutableListOf("Kotlin", "Java", "Scala") 22 | list.sort() 23 | println(list) 24 | 25 | for (c in '0' until '9') { 26 | print(c) 27 | } 28 | for (c in '0'..'8') { 29 | print(c) 30 | } 31 | // 012345678 32 | 33 | } -------------------------------------------------------------------------------- /tasks/src/_1Intro/_2Foo.kt: -------------------------------------------------------------------------------- 1 | package questions.i_intro 2 | 3 | val foo1 = run { 4 | println("Calculating foo...") 5 | "foo" 6 | } 7 | 8 | fun foo2(): String { 9 | println("Calculating foo...") 10 | return "foo" 11 | } 12 | 13 | fun main(args: Array) { 14 | println("======") 15 | println("First $foo1, second $foo1") 16 | println("------") 17 | println("First ${foo2()}, second ${foo2()}") 18 | } -------------------------------------------------------------------------------- /tasks/src/_2Extensions/Extensions.kt: -------------------------------------------------------------------------------- 1 | package _2Extensions 2 | 3 | // Try 'convert receiver to parameter' 4 | // and 'convert parameter to receiver' actions 5 | fun List.sum(): Int { 6 | var result = 0 7 | for (i in this) { 8 | result += i 9 | } 10 | return result 11 | } 12 | 13 | fun main(args: Array) { 14 | val sum = listOf(1, 2, 3).sum() 15 | println(sum) 16 | } -------------------------------------------------------------------------------- /tasks/src/_2Extensions/MemberVsExtension.kt: -------------------------------------------------------------------------------- 1 | package _2Extensions 2 | 3 | fun String.get(index: Int) = '*' 4 | 5 | fun main(args: Array) { 6 | println("abc".get(1)) // b 7 | } 8 | -------------------------------------------------------------------------------- /tasks/src/_2Extensions/ParentVsChild.kt: -------------------------------------------------------------------------------- 1 | package _2Extensions 2 | 3 | open class Parent 4 | class Child: Parent() 5 | 6 | fun Parent.foo() = "parent" 7 | 8 | fun Child.foo() = "child" 9 | 10 | fun main(args: Array) { 11 | val parent: Parent = Child() 12 | println(parent.foo()) 13 | } -------------------------------------------------------------------------------- /tasks/src/_2Extensions/ParentVsChildJava.java: -------------------------------------------------------------------------------- 1 | package _2Extensions; 2 | 3 | public class ParentVsChildJava { 4 | public static void main(String[] args) { 5 | Parent parent = new Child(); 6 | System.out.println(foo(parent)); 7 | System.out.println(ParentVsChildKt.foo(parent)); 8 | } 9 | 10 | private static String foo(Parent parent) { 11 | return "parent"; 12 | } 13 | 14 | private static String foo(Child child) { 15 | return "child"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tasks/src/_2Extensions/RepeatExample.kt: -------------------------------------------------------------------------------- 1 | package _2Extensions 2 | 3 | fun String.repeat(n: Int) = buildString { 4 | for (i in 1..n) { 5 | append(this@repeat) 6 | } 7 | } 8 | 9 | fun main(args: Array) { 10 | println("ab".repeat(3)) // ababab 11 | } -------------------------------------------------------------------------------- /tasks/src/_2Extensions/UsingRepeatFromJava.java: -------------------------------------------------------------------------------- 1 | package _2Extensions; 2 | 3 | public class UsingRepeatFromJava { 4 | public static void main(String[] args) { 5 | System.out.println(RepeatExampleKt.repeat("ab", 3)); // ababab 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tasks/src/_3Classes/Evaluation.kt: -------------------------------------------------------------------------------- 1 | package questions.ii_classes 2 | 3 | class TwoNumbers1(val first: Int, val second: Int) 4 | data class TwoNumbers2(val first: Int, val second: Int) 5 | 6 | fun test1() { 7 | val p1 = TwoNumbers1(1, 3) 8 | val p2 = TwoNumbers1(1, 3) 9 | println(p1 == p2) // false 10 | } 11 | 12 | fun test2() { 13 | val p1 = TwoNumbers2(1, 3) 14 | val p2 = TwoNumbers2(1, 3) 15 | println(p1 == p2) // true 16 | } 17 | 18 | fun main(args: Array) { 19 | test1() 20 | test2() 21 | } 22 | -------------------------------------------------------------------------------- /tasks/src/_3Classes/Foo.kt: -------------------------------------------------------------------------------- 1 | package questions.ii_classes 2 | 3 | val foo1 = run { 4 | println("Calculating the answer... (1)") 5 | 42 6 | } 7 | 8 | val foo2: Int 9 | get() { 10 | println("Calculating the answer... (2)") 11 | return 42 12 | } 13 | 14 | fun main(args: Array) { 15 | println("foo1:") 16 | println(foo1) 17 | println(foo1) 18 | println("foo2:") 19 | println(foo2) 20 | println(foo2) 21 | } -------------------------------------------------------------------------------- /tasks/src/_3Classes/InnerAndNested.kt: -------------------------------------------------------------------------------- 1 | package _3Classes 2 | 3 | class Outer { 4 | class A { 5 | fun foo() { 6 | // this@Outer 7 | } 8 | } 9 | inner class B { 10 | fun foo() { 11 | this@Outer 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /tasks/src/_3Classes/Person.kt: -------------------------------------------------------------------------------- 1 | package questions.ii_classes 2 | 3 | class Person(val name: String, var age: Int) -------------------------------------------------------------------------------- /tasks/src/_3Classes/UsePersonFromJava.java: -------------------------------------------------------------------------------- 1 | package _3Classes; 2 | 3 | import questions.ii_classes.Person; 4 | 5 | public class UsePersonFromJava { 6 | public static void main(String[] args) { 7 | // constructor 8 | Person person = new Person("Alice", 27); 9 | 10 | // 2 getters 11 | System.out.println(person.getName()); 12 | System.out.println(person.getAge()); 13 | 14 | // 1 setter 15 | person.setAge(28); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tasks/src/_3Classes/Visibility.kt: -------------------------------------------------------------------------------- 1 | package _3Classes 2 | 3 | fun main(args: Array) { 4 | foo() 5 | // C().bar() 6 | } 7 | 8 | private fun foo() {} 9 | 10 | class C { 11 | private fun bar() {} 12 | 13 | inner class A { 14 | fun foo() = bar() 15 | } 16 | } -------------------------------------------------------------------------------- /tasks/src/_4Nullability/Lists.kt: -------------------------------------------------------------------------------- 1 | package questions.iii_nullability 2 | 3 | fun foo(list1: List, list2: List?) { 4 | list1.size 5 | list2?.size 6 | 7 | val i: Int? = list1.get(0) 8 | val j: Int? = list2?.get(0) 9 | } 10 | -------------------------------------------------------------------------------- /tasks/src/_4Nullability/Name.kt: -------------------------------------------------------------------------------- 1 | package questions.iii_nullability 2 | 3 | class Name(val value: String?) 4 | 5 | fun isFoo1(n: Name) = n.value == "foo" 6 | //fun isFoo2(n: Name?) = n.value == "foo" 7 | fun isFoo3(n: Name?) = n != null && n.value == "foo" 8 | fun isFoo4(n: Name?) = n?.value == "foo" 9 | 10 | fun main(args: Array) { 11 | // isFoo1(null) 12 | // isFoo2(null) 13 | isFoo3(null) 14 | isFoo4(null) 15 | } 16 | -------------------------------------------------------------------------------- /tasks/src/_4Nullability/SafeCasts.kt: -------------------------------------------------------------------------------- 1 | package _4Nullability 2 | 3 | fun main(args: Array) { 4 | val s = "abc" 5 | println(s as Int?) 6 | println(s as? Int) 7 | } -------------------------------------------------------------------------------- /tasks/src/_4Nullability/isNullOrEmpty.kt: -------------------------------------------------------------------------------- 1 | package questions.iii_nullability 2 | 3 | fun main(args: Array) { 4 | val s1: String? = null 5 | val s2: String? = "" 6 | println(s1.isNullOrEmpty() && s2.isNullOrEmpty()) 7 | } 8 | 9 | fun String?.isNullOrEmpty(): Boolean = this == null || this.isEmpty() -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/JavaClass.java: -------------------------------------------------------------------------------- 1 | package _5TypeSystem; 2 | 3 | import java.util.List; 4 | 5 | public class JavaClass { 6 | public String getValue() { 7 | return null; 8 | } 9 | 10 | public static void dangerousJavaMethod(List list) { 11 | list.add(null); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/Parent.java: -------------------------------------------------------------------------------- 1 | package _5TypeSystem; 2 | 3 | public class Parent { 4 | public Parent() { 5 | 6 | getFoo().length(); 7 | } 8 | 9 | String getFoo() { 10 | return ""; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/Subclass.java: -------------------------------------------------------------------------------- 1 | package _5TypeSystem; 2 | 3 | public class Subclass extends Parent { 4 | private String foo; 5 | 6 | public Subclass(String foo) { 7 | this.foo = foo; 8 | } 9 | 10 | @Override 11 | String getFoo() { 12 | return foo; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/Usage.java: -------------------------------------------------------------------------------- 1 | package _5TypeSystem; 2 | 3 | public class Usage { 4 | public static void main(String[] args) { 5 | Subclass subclass = new Subclass(""); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/_1NPE.kt: -------------------------------------------------------------------------------- 1 | package _5TypeSystem 2 | 3 | fun mightThrowNPE() { 4 | println(JavaClass().value.length) 5 | } 6 | 7 | fun main(args: Array) { 8 | mightThrowNPE() // throws NPE, because getValue() returns null 9 | } -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/_2ExplicitTypeSpecification.kt: -------------------------------------------------------------------------------- 1 | package _5TypeSystem 2 | 3 | fun explicitType() { 4 | val value: String = JavaClass().value // IllegalStateException: JavaClass().value must not be null 5 | println(value.length) 6 | } 7 | 8 | fun main(args: Array) { 9 | explicitType() 10 | } -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/_2NullInList.kt: -------------------------------------------------------------------------------- 1 | package _5TypeSystem 2 | 3 | import _5TypeSystem.JavaClass.dangerousJavaMethod 4 | 5 | fun mightContainNull(): List { 6 | val list: List = arrayListOf(1, 2, 3) 7 | // change the implementation of the `dangerousJavaMethod` 8 | // so that it add `null` values in the list 9 | dangerousJavaMethod(list) 10 | return list 11 | } 12 | 13 | fun main(args: Array) { 14 | for (i in mightContainNull()) { // NPE 15 | println(i) 16 | } 17 | } -------------------------------------------------------------------------------- /tasks/src/_5TypeSystem/_3NPEDuringInitialization.kt: -------------------------------------------------------------------------------- 1 | package _5TypeSystem 2 | 3 | open class A(open val value: String) { 4 | init { 5 | 6 | } 7 | } 8 | 9 | class B(override val value: String) : A(value) 10 | 11 | fun main(args: Array) { 12 | // Complete the declaration of the class A 13 | // so that NPE is thrown during the creation of its subclass B instance 14 | B("a") 15 | } -------------------------------------------------------------------------------- /tasks/src/_6Lambdas/Heroes.kt: -------------------------------------------------------------------------------- 1 | package _6Lambdas 2 | 3 | import _6Lambdas.Gender.FEMALE 4 | import _6Lambdas.Gender.MALE 5 | 6 | class Hero(val name: String, val age: Int, val gender: Gender?) 7 | enum class Gender { MALE, FEMALE } 8 | 9 | fun main(args: Array) { 10 | val heroes = listOf( 11 | Hero("The Captain", 60, MALE), 12 | Hero("Frenchy", 42, MALE), 13 | Hero("The Kid", 9, null), 14 | Hero("Lady Lauren", 29, FEMALE), 15 | Hero("First Mate", 29, MALE), 16 | Hero("Sir Stephen", 37, MALE)) 17 | 18 | println(heroes.last().name) 19 | 20 | println(heroes.firstOrNull { it.age == 30 }?.name) 21 | println(heroes.last { it.age == 29 }.name) 22 | 23 | println(heroes.map { it.age }.distinct().size) 24 | println(heroes.filter { it.age < 30 }.size) 25 | 26 | val (youngest, oldest) = heroes.partition { it.age < 30 } 27 | println(oldest.size) 28 | println(youngest.size) 29 | 30 | println(heroes.maxBy { it.age }?.name) 31 | 32 | println(heroes.all { it.age < 50 }) 33 | println(heroes.any { it.gender == FEMALE }) 34 | 35 | 36 | val mapByAge: Map> = heroes.groupBy { it.age } 37 | val (age, group) = mapByAge.maxBy { (_, group) -> group.size }!! 38 | println(age) 39 | println(group.size) 40 | 41 | val mapByName: Map = heroes.associateBy { it.name } 42 | println(mapByName["Frenchy"]?.age) 43 | println(mapByName.getValue("Frenchy").age) 44 | println(mapByName["unknown"]) 45 | 46 | val unknownCharacter = Hero("Unknown", 0, null) 47 | println(mapByName.getOrElse("unknown") { unknownCharacter }.age) 48 | 49 | val (first, second) = heroes 50 | .flatMap { heroes.map { hero -> it to hero } } 51 | .maxBy { it.first.age - it.second.age }!! 52 | println(first.name) 53 | println(second.name) 54 | } -------------------------------------------------------------------------------- /tasks/src/_7InlineAndLazyIteration/Inline.kt: -------------------------------------------------------------------------------- 1 | package _7InlineAndLazyIteration 2 | 3 | fun main(args: Array) { 4 | 5 | val list = listOf(1, 2, 3) 6 | val result = list.filter { it > 0 } 7 | 8 | 9 | } 10 | 11 | inline fun List.filter(predicate: (T) -> Boolean): List { 12 | val destination = ArrayList() 13 | for (element in this) { 14 | if (predicate(element)) { 15 | destination.add(element) 16 | } 17 | } 18 | return destination 19 | } -------------------------------------------------------------------------------- /tasks/src/_7InlineAndLazyIteration/IntermediateCollections.kt: -------------------------------------------------------------------------------- 1 | package _7InlineAndLazyIteration 2 | 3 | fun main(args: Array) { 4 | collectionExample() 5 | println() 6 | sequenceExample() 7 | } 8 | 9 | fun collectionExample() { 10 | val list = listOf(1, 2, -3) 11 | val mapResult = list.map { it * it } 12 | println(mapResult) 13 | val filterResult = mapResult.filter { it % 2 == 1 } 14 | println(filterResult) 15 | val maxOddSquare = filterResult.max() 16 | println(maxOddSquare) 17 | } 18 | 19 | fun sequenceExample() { 20 | val sequence = listOf(1, 2, -3).asSequence() 21 | val mapResult = sequence.map { it * it } 22 | println(mapResult) 23 | val filterResult = mapResult.filter { it % 2 == 1 } 24 | println(filterResult) 25 | val maxOddSquare = filterResult.max() 26 | println(maxOddSquare) 27 | } -------------------------------------------------------------------------------- /tasks/src/_7InlineAndLazyIteration/LazyIteration.kt: -------------------------------------------------------------------------------- 1 | package _7InlineAndLazyIteration 2 | 3 | // Eager and lazy evaluation 4 | 5 | fun m(i: Int): Int { 6 | print("m$i ") 7 | return i * i 8 | } 9 | 10 | fun f(i: Int): Boolean { 11 | print("f$i ") 12 | return i % 2 == 0 13 | } 14 | 15 | fun main(args: Array) { 16 | val list = listOf(1, 2, 3, 4) 17 | 18 | list.map(::m).filter(::f) 19 | 20 | println() 21 | 22 | list.asSequence().map(::m).filter(::f).toList() 23 | 24 | println() 25 | 26 | list.asSequence().map(::m).filter(::f) 27 | 28 | println() 29 | 30 | list.asSequence().filter(::f).map(::m).toList() 31 | 32 | } --------------------------------------------------------------------------------