User Tools

Site Tools


elements_of_kotlin

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
elements_of_kotlin [2023/10/19 17:54] – [Properties] kalaschnikowelements_of_kotlin [2023/10/24 16:36] (current) – [Abstract Classes and Interfaces] kalaschnikow
Line 1: Line 1:
 +====== Elements of Kotlin ======
  
 +[[https://commonsware.com/Kotlin/|Elements of Kotlin]] - by Mark L. Murphy
 +
 +[[https://commonsware.com/Kotlin/pages/index|Outline]]
 +===== Introducing Kotlin =====
 +
 +==== Why? ====
 +    * 2017 - Kotlins popularity exploded as Google announced support for Kotlin for Android apps
 +    * originally created as replacement for Java
 +    * Kotlin is designed to be more concise as Java
 +      * e.g. semicolon is optional in Kotlin
 +==== ...And Why Not? ====
 +    * Kotlin is a complex language
 +    * Kotlin lends itself to be terse
 +      * "concise" -> short but understandable
 +      * "terse" -> short but not understandable
 +
 +==== What You Need to Know ====
 +    * class-based language
 +      * like Java
 +      * JavaScript previously was not, but now it is moved in this direction
 +    * functions 
 +      * ("methods" in Java)
 +    * properties
 +      * ("fields" in Java)
 +    * variables
 +      * save working data inside functions
 +
 +==== Look At All the Kotlins! ====
 +  * Runtime environments to run compiled Kotlin code:
 +    * Kotlin/JVM 
 +      * most used environment
 +    * Kotlin/JS
 +      * Kotlin "compiled" into JavaScript code 
 +        * => simple JavaScript (but not really readable by humans :))
 +    * Kotlin/Native
 +      * mostly used in iOS environment
 +    * Kotlin/Common
 +      * not really an environment
 +      * it is a library that limits Kotlin code to guarantee that this code can be used all on other platforms (JVM, JS etc)
 +    * Kotlin/Multiplatform
 +      * a way of setting up a project such that some core app logic is written in a Kotlin/Common library, while other “modules” are set up for specific runtime environments.
 +      * used for example to create one code base for Android and iOS apps
 +
 +==== Getting Kotlin, Normally ====
 +
 +  * normally it will be done by IDE (for Android -> Android Studio)
 +    * there are Gradle plugins for it etc
 +  * it is also possible to download a standalone Kotlin compiler 
 +
 +==== Introducing the Klassbook ====
 +  * An easy way to experiment with a programming language is to use a REPL.
 +    * Read typed-in source code, 
 +    * Evaluate it, 
 +    * Print the results of that evaluation in the tool
 +    * Loop back to process more input.
 +  * [[https://klassbook.commonsware.com/|Klassbook]] is a REPL set up for use with this book. 
 +==== How This Book is Structured ====
 +  * This book has two objectives:
 +    * Help you start writing basic Kotlin code
 +    * Help you start reading advanced Kotlin code
 +  * This book is divided into two major sets of chapters: 
 +    * core chapters
 +      * basic Kotlin syntax
 +      * mostly used Kotlin idioms
 +    * “WTF?” chapters
 +      * advanced Kotlin
 +
 +
 +===== A Few “Hello, World!” Examples =====
 +
 +...
 +
 +==== So, What Does This Do? ====
 +
 +...
 +
 +  * ''HelloWorld().speak()''
 +    * In Kotlin: just use the class name like a function. So, ''HelloWorld()'' returns an instance of a HelloWorld object. There is no need for a keyword, the way Java, Ruby, or JavaScript uses ''new''.
 +
 +  * Kotlin is a “strongly typed” language: everything in Kotlin is tied to some type.
 +
 +==== Using the Klassbook ====
 +...
 +
 +==== Running These Snippets in an IDE ====
 +  * Android Studio and IntelliJ IDEA each has a Kotlin REPL, available from the Tools > Kotlin > Kotlin REPL main menu option
 +  * In Android Studio is also possible to use scratch files to run short examples
 +===== Basic Types and Expressions =====
 +
 +Kotlin’s basic types are modeled somewhat after Java, as Kotlin’s original target environment was the JVM.
 +
 +But there are also some differences.
 +
 +==== Basic Types and “Objectness” ====
 +
 +  * In Kotlin everything is an object
 +    * In Java: basic types are “primitives”, but have object counterparts
 +      * e.g. ''int'' -> ''Integer''
 +
 +==== Numbers ====
 +  * There are four integral types:
 +    * Byte (8-bit representation)
 +    * Short (16 bits)
 +    * Int (32 bits)
 +    * Long (64 bits)
 +  * Two floating-point types:
 +    * Float (32 bits)
 +    * Double (64 bits)
 +  * Number Literals
 +    * by default ''Int'' or ''Double''
 +    * if you want a ''Long'', use ''L'' suffix
 +      * ''12345L''
 +    * if you want a ''Float'', use ''F'' suffix
 +      * ''1.2345f''
 +    * For longer numbers, if you like, you can use underscores for the “thousands separator”:
 +      * ''1_234''
 +      * Technically, those underscores can go anywhere, so ''1_2_3_4'' is also perfectly valid.
 +    * For integral types, the default representation is decimal format. 
 +      * hexadecimal by using an ''0x'' prefix 
 +      * ''0xFFA4C639''
 +      * binary literals by using an ''0b'' prefix 
 +        * ''0b10110100''
 +  * Mathematical Expressions
 +    * ''+'' for addition
 +    * ''-'' for subtraction
 +    * ''*'' for multiplication
 +    * ''/'' for division
 +    * ''%'' for the remainder after division (“modulo”)
 +
 +==== Boolean ====
 +  * ''true'' or ''false''
 +  * Boolean operators:
 +    * ''&&'' -> AND
 +    * ''||'' -> OR
 +    * ''!'' -> NOT
 +
 +==== Strings ====
 +
 +  * String Quoting Options
 +    * two possible options:
 +      * ''"'' - double-quotes
 +        * like in Java
 +          * cannot contain newlines
 +          * special characters, such as newlines or tabs, need to be indicated via “escape sequences”
 +            * ''\n'', ''\t'' etc.
 +      * ''"""'' - triple-quotes
 +        * does not support escape sequences but does support embedded newlines, tabs, and anything else
 +        * this allows you to directly express strings that otherwise would be a mess of text and escape sequences, resulting in more readable code.
 +        * but indents then become a problem
 +          * use ''trimMargin()'' function on String to eliminate unwanted indentation.
 +  * String Expressions
 +    * Concatenation: ''"one" + "two"''
 +    * Kotlin also supports "string interpolation"
 +      * ''"The value of count is $count"''
 +      * ''"The value of count is ${count+2}"''
 +
 +==== Characters ====
 +
 +  * Use single quotes to declare a single character:
 +    * ''println('A')''
 +
 +==== A Quick Note About Equality ====
 +
 +  * ''=='' -> means "content equality"
 +    * (like ''equals()'' in Java)
 +  * ''==='' -> means "instance equality" 
 +    * (like ''=='' in Java)
 +
 +  * What you get as the result of an instance equality check (''==='') is determined a bit by Kotlin but mostly by the Kotlin environment. 
 +
 +<code kotlin>
 +val value = "something"
 +println(value.toUpperCase().toLowerCase() == value)   // prints true
 +println(value.toUpperCase().toLowerCase() === value)  // prints false in Kotlin/JVM and true in Kotlin/JS
 +</code>
 +===== Variables… Whether They Vary or Not =====
 +
 +==== Declaring Variables ====
 +
 +  * Do you need a keyword, like var, or not?
 +    * -> yes
 +  * Do you need a data type, like int, or not?
 +    * -> not always
 +  * Do you need to provide an initializer to establish the variable’s value, or not?
 +    * -> not always
 +
 +  * Typeless Declaration
 +    * ''var myVar = 5''
 +      * ''myVar::class'' will be ''kotlin.Int'' (in Kotlin/JVM environment) 
 +  * Typed Declaration
 +    * ''var count: Long = 5''
 +
 +==== Declaring Read-Only Variables ====
 +
 +  * Declare "read-only" variables with keyword ''val''
 +  * Reassigning value to a ''val'' will result in an exception
 +  * Prefer ''val'' Over ''var''
 +    * use ''var'' only if it is necessary
 +
 +==== String Interpolation ====
 +
 +  * For a simple variable reference, you can skip the braces and just use $:
 +<code>
 +  val count = 5
 +  println("The value of count is $count")
 +</code>
 +
 +Arbitrary Kotlin expressions can be used with ${} syntax:
 +<code>
 +val count = 3
 +println("The value of count is not ${count+2}")
 +</code>
 +
 +
 +==== More Operators ====
 +
 +  * Mathematical expressions
 +    * ''+'', ''-'', ''/'', ''%'' etc
 +  * Increment and decrement
 +    * postincrement++, ++preincrement
 +    * postdecrement--, --predecrement
 +  * Augmented Assignments
 +    * ''+='', ''-='', ''*='', ''/='', ''%=''
 +    * example: ''count += 2''
 +  * Unary Operators (inverting)
 +    * ''-count'' (negation)
 +    * ''!count'' (''true'' will be ''false'' and vice versa)
 +
 +==== No Automatic Number Conversions ====
 +
 +This will not work in Kotlin:
 +<code kotlin>
 +val thisIsInt = 5
 +val thisIsLong : Long = thisIsInt
 +</code>
 +(but it works in Java)
 +
 +In Kotlin the code should be:
 +<code kotlin>
 +val thisIsInt = 5
 +val thisIsLong : Long = thisIsInt.toLong()
 +</code>
 +
 +==== Hey, What About ? ====
 +  * We can assign ''null'' to a variable whose type ends in ''?'', and we //cannot// assign ''null'' to a variable whose type does not end in ''?''.
 +<code kotlin>
 +var something : Boolean? = null
 +println("something was: $something")
 +
 +something = true
 +println("something is now: $something")
 +</code>
 +
 +
 +===== Functions =====
 +
 +====Functions with Parameters====
 +<code kotlin>
 +fun lessTrivial(left: Int, right: Int) {
 +  println(left + right)
 +}
 +</code>
 +
 +At first the parameter name and then colon and the parameter type.
 +====Functions with Return Types====
 +
 +<code kotlin>
 +fun simpleReturn(left: Int, right: Int) : Int {
 +  return left + right
 +}
 +</code>
 +
 +  * Return type is at the end after the colon and before the curly brace (''Int'' in this example).
 +  * Functions without ''return'' keyword returns nothing (''void'' in Java), but technically seen they return ''Unit''.
 +====Local Variables====
 +
 +<code kotlin>
 +fun actLocally(left: Int, right: Int) : Int {
 +  val result = left + right
 +
 +  return result
 +}
 +</code>
 +====Fancier Functions====
 +
 +Expression bodies:
 +<code kotlin>
 +fun expressionBody(left: Int, right: Int) = left + right
 +</code>
 +
 +Expression Bodies and Types:
 +<code kotlin>
 +fun expressionBody(left: Int, right: Int):Number = left + right
 +</code>
 +
 +''Number'' is a super type of ''Int'' and sometimes it could be necessary to use it instead of ''Int''. 
 +
 +Default parameter values:
 +<code kotlin>
 +fun main() {
 +  println(increment(1))
 +}
 +
 +fun increment(base: Int, amount: Int = 1) = base + amount
 +</code>
 +
 +Named parameters:
 +<code kotlin>
 +fun main() {
 +  println(increment(base = 1))
 +  println(increment(amount = 10, base = 1))
 +  println(increment(1, amount = 10))
 +}
 +
 +fun increment(base: Int, amount: Int = 1) = base + amount
 +</code>
 +
 +It is a simple example and it does not make much sense. But sometimes it is really helpful. For example:
 +<code kotlin>
 +fun main() {
 +  val cookieHeader = iCanHazCookie(name = "foo", value = "bar", path = "/")
 +
 +  // or even:
 +  cookieHeader = iCanHazCookie("foo", "bar", path = "/")
 +}
 +
 +
 +
 +fun iCanHazCookie(name: String,
 +                  value: String,
 +                  maxAge: Long? = null,
 +                  expires: LocalDateTime? = null,
 +                  domain: String? = null,
 +                  path: String? = null,
 +                  secure: Boolean = false,
 +                  httpOnly: Boolean = false) : String {
 +  // code to generate an HTTP Set-cookie header goes here
 +  // ...
 +}
 +</code>
 +Traditionally, named parameters had to appear after all positional parameters. Kotlin 1.4 relaxed that restriction somewhat. You can use names for any parameters, but up through the last positional parameter, the positions (not the names) are what matter.
 +===== Collections and Lambdas =====
 +Major collection types are like in the other popular modern languages:
 +  * arrays or lists
 +  * sets (collections of distinct unequal objects)
 +  * maps (collections of key/value pairs)
 +
 +==== Major Collection Types and Creation Functions ====
 +
 +Kotlin has the aforementioned roster of collection types, and they form the most common collection types that you will use.
 +
 +Kotlin/JVM also has access to other standard Java collection types, like LinkedHashMap, which we will discuss later in this chapter. However, usually you will use those only if there is no native Kotlin equivalent.
 +
 +  * Arrays
 +    * the simplest way to create an array:
 +      * ''val things = arrayOf("foo", "bar", "goo")''
 +    * Typed arrays:
 +      * ''BooleanArray'', ''ByteArray'', ''CharArray'', ''DoubleArray'', ''FloatArray'',''IntArray'', ''LongArray'', ''ShortArray''
 +      * They have corresponding utility functions to create instances, such as ''intArrayOf()'':
 +        * ''val things = intArrayOf(1, 3, 3, 7)''
 +    * Lists
 +      * can be created like Arrays:
 +        * ''listOf("foo", "bar", "goo")''
 +    * Sets
 +      * is a one-dimensional collection in which only distinct objects will be included. 
 +        * For example, if you try adding the four numbers 1, 3, 3, 7 to a list, you would have four entries, but adding them to a set results in a three-element set holding 1, 3, 7. The duplicate 3 value is ignored.
 +      * creation:
 +        * ''val things = setOf(1, 3, 3, 7)''
 +        * (will contain only ''1,3,7'')
 +      * As with ''List'', ''Set'' is an interface. The concrete implementation that you will get from ''setOf()'' is a ''LinkedHashSet''
 +      * And, as with lists, ''setOf()'' creates an immutable Set
 +    * Maps
 +      * To create a hard-coded map — the way we have created hard-coded lists and sets — you can use the ''mapOf()'' utility function. This takes a comma-delimited list of key-value pairs, where the key and value are separated by the ''to'' keyword
 +      * ''mapOf("key" to "value", "other-key" to "other-value")''
 +      * it is also possible to mix these constructs (e.g. use Lists as values for Maps)
 +        * ''mapOf("odd" to listOf(1, 3, 5, 7, 9), "even" to listOf(2, 4, 6, 8))''
 +
 +==== Basic Usage ====
 +
 +  * [] Syntax
 +    * To retrieve values from a collection (other than a Set), you can use []. For example:
 +      * ''thingsArray[0]''
 +  * Typical Stuff
 +    * ''size()''
 +    * ''isEmpty()'', for a quick Boolean value based on whether the collection is empty
 +    * ''contains()'', which will return true if the collection contains the requested item (for maps, this checks the keys — use ''containsValue()'' to check the values)
 +    * For lists and arrays, you have things like:
 +      * ''first()'', to get the first element
 +      * ''last()'', to get the last element
 +      * ''firstOrNull()'', to get the first element or null if the collection is empty
 +      * And so on
 +    * Conversion Functions
 +      * ''Array'' offers 
 +        * ''toList()'' 
 +        * ''toSet()''
 +      * ''List'' offers 
 +        * ''toSet()'' 
 +        * ''toTypedArray()''
 +      * ''Set'' offers 
 +        * ''toList()''
 +        * ''toTypedArray()''
 +
 +
 +
 +==== Immutability and Collections ====
 +
 +Array objects that we create with ''arrayOf()'' are mutable. Not only can we use ''[]'' syntax to retrieve a value based on its index, but we can use ''[]='' syntax to replace a value based on its index.
 +
 +<code kotlin>
 +val thingsArray = arrayOf("foo", "bar", "goo")
 +
 +thingsArray[1] = "something completely different"
 +</code>
 +
 +However, this fails if you try it with a List created using ''listOf()'':
 +<code kotlin>
 +val thingsList = listOf("foo", "bar", "goo")
 +
 +thingsList[1] = "something completely different"
 +</code>
 +
 +A List is immutable: you cannot replace its members with other objects.
 +
 +If you need a list where you can replace its members, you can use ''mutableListOf()'':
 +<code kotlin>
 +val thingsList = mutableListOf("foo", "bar", "goo")
 +
 +thingsList[1] = "something completely different"
 +</code>
 +
 +The same distinction holds true for ''Map''. A ''Map'' is immutable, but a ''MutableMap'' created via ''mutableMapOf()'' can be modified.
 +==== Introducing Lambda Expressions ====
 +  * Lambda expressions are important to do the following:
 +    * Looping over the elements
 +    * Finding or filtering elements that match certain criteria
 +    * Providing comparison logic for sorting elements
 +    * ...
 +
 +  * What is a Lambda Expression?
 +    * A simple way to start thinking about lambda expressions is to consider them just as a set of Kotlin statements wrapped in curly braces:
 +      * ''val lambda = { println("Hello, world!") }''
 +      * A lambda expression itself is an object. 
 +        * You can hold onto them in variables, 
 +        * pass them as function parameters, 
 +        * and do everything else that you might do with other types of objects.
 +      * If you receive a lambda expression, and you want to run it, call ''invoke()'':
 +<code kotlin>
 +val lambda = { println("Hello, world!") }
 +
 +lambda.invoke()
 +</code>
 +  * Where Do We Use Lambda Expressions?
 +    * At minimum, lambda expressions replace a lot of the “listener” or “callback” patterns that you might have used in Java.
 +  * Lambda Expressions, Parameters, and Return Values
 +    * Like functions, lambda expressions can take parameters:
 +      * <code kotlin>
 +val squarifier = { x: Int -> x * x }
 +
 +println(squarifier.invoke(3))
 +</code>
 +      * single-parameter lambdas are very common. For that, Kotlin offers a shorthand syntax: it. If the Kotlin compiler can determine the data type for the parameter, you can skip the parameter declaration and just refer to the parameter as it.
 +      *  A lambda expression will return whatever its last statement does.
 +
 +
 +
 +
 +
 +==== Common Collection Operations ====
 +
 +  * Iteration (''forEach()'' and ''for'')
 +    * ''forEach()''
 +      * <code kotlin>
 +val things = listOf("foo", "bar", "goo")
 +
 +things.forEach { println(it) }
 +</code>
 +      * ''forEach()'' takes a lambda expression as a parameter. It may not look like a parameter, again due to the lack of parentheses. The same code:
 +        * <code kotlin>
 +val things = listOf("foo", "bar", "goo")
 +
 +things.forEach( { println(it) } )
 +</code>
 +      * The lambda expression takes a single parameter. The type of the parameter is determined by the definition of ''forEach()'' — just as a function can declare a parameter as being an Int or a String, it can declare a parameter as being a lambda expression that itself takes a certain parameter.
 +    * ''for''
 +      * <code kotlin>
 +val things = listOf("foo", "bar", "goo")
 +
 +for (thing in things) {
 +  println(thing)
 +}
 +</code>
 +      * ''forEach()'' is somewhat more popular as ''for'', as it can be used in chained expressions.
 +    * ''filter()''
 +      * ''filter()'' applies a filtering lambda expression to a collection, returning a new collection that contains the subset of items from the original collection. If the lambda expression returns true for an item, that item is included in the result collection, otherwise it is not.
 +      * <code kotlin>
 +val things = listOf("foo", "bar", "goo")
 +
 +things.filter { it[1]=='o' }.forEach { println(it) }
 +</code>
 +    * ''map()''
 +      * ''filter()'' passes along a strict subset of the items in the collection, but the items themselves are unchanged. ''map()'', by contrast, passes along each item from the collection, transformed by a lambda expression that you supply:
 +      * <code kotlin>
 +val things = listOf("foo", "bar", "goo")
 +
 +things
 +  .map { it.toUpperCase() }
 +  .forEach { println(it) }
 +</code>
 +      * whereas ''filter()'' takes a collection and returns a subset of its items, ''map()'' takes a collection and returns a transformed representation of its items.
 +
 +==== Varargs ====
 +<code kotlin>
 +fun main() {
 +  reciprocate(1, 2, 3, 5, 7)
 +}
 +
 +fun reciprocate(vararg values: Int) {
 +  values
 +    .map { 1.0 / it }
 +    .forEach { println(it) }
 +}
 +</code>
 +
 +In addition, Kotlin offers special support for an existing Array. If you already have an Array with the values that you want to supply, but the function that you are calling uses vararg (instead of an Array parameter), you can use the “spread operator”
 +<code kotlin>
 +fun main() {
 +  val things = arrayOf("foo", "bar", "goo")
 +
 +  capped(*things).forEach { println(it) }
 +}
 +
 +fun capped(vararg strings: String) = strings.map { it.toUpperCase() }
 +</code>
 +
 +Things get a bit strange with types that map to primitives, though. ''vararg'' expects the dedicated array types to be used with the spread operator. So, in the following example, the ''reciprocate()'' function takes a ''vararg'' of ''Int''. For the spread operator to work, we need to use an ''IntArray'', not a regular ''Array'':
 +<code kotlin>
 +fun main() {
 +  val primes = intArrayOf(1, 2, 3, 5, 7)
 +
 +  reciprocate(*primes)
 +}
 +
 +fun reciprocate(vararg values: Int) {
 +  values
 +    .map { 1.0 / it }
 +    .forEach { println(it) }
 +}
 +</code>
 +
 +==== Other JVM Collections ====
 +If you are using Kotlin/JVM — for example, if you are using Kotlin for ordinary Android app development — you are welcome to use other JVM collection types, such as ''LinkedList''. On the whole, you should stick with Kotlin collection types where possible, as the Kotlin types are more “natural” for use in Kotlin. But sometimes you will find a Java class that fits your scenario better, such as using a ''LinkedHashMap'' to implement an LRU-style cache.
 +==== get() and [] Syntax ====
 +In reality, ''[]'' syntax is available for anything that offers a one-parameter ''get()'' function. When Kotlin encounters ''[]'' syntax, it simply replaces that with the corresponding ''get()'' call.
 +
 +
 +===== If, When, and While =====
 +
 +==== If ====
 +
 +<code kotlin>
 +val i = 3
 +
 +if (i > 10) {
 +  println("something")
 +}
 +else {
 +  println("something else")
 +}
 +</code>
 +
 +''else'' is optional:
 +<code kotlin>
 +val i = 3
 +
 +if (i > 10) {
 +  println("something")
 +}
 +
 +println("the if is done")
 +</code>
 +
 +For single-line conditional work, you can skip the braces:
 +<code kotlin>
 +val i = 3
 +
 +if (i>10) println("something") else println("something else")
 +</code>
 +
 +''else if'' is also possible:
 +<code kotlin>
 +val i = 3
 +
 +if (i > 10) {
 +  println("something")
 +}
 +else if (i > 2) {
 +  println("something else")
 +}
 +else {
 +  println("and now for something completely different")
 +}
 +</code>
 +However, as you will see in the next section, the convention in Kotlin development is to use ''when'' instead of ''if'' for such scenarios.
 +==== When ====
 +
 +Basic syntax:
 +
 +<code kotlin>
 +val thingy = "foo"
 +
 +when (thingy) {
 +  "foo" -> println("something")
 +  "bar" -> println("something else")
 +  else -> println("and now for something completely different")
 +}
 +</code>
 +
 +However, you cannot mix types, unless == happens to work to compare them.
 +
 +It is possible to skip the parameter to the ''when''. In that case, each branch has its own Boolean expression, and the first that evaluates to true is used:
 +<code kotlin>
 +val i = 3
 +
 +when {
 +  i > 10 -> println("something")
 +  i > 2 -> println("something else")
 +  else -> println("and now for something completely different")
 +}
 +</code>
 +
 +Also we can consolidate multiple branches:
 +<code kotlin>
 +val thingy = "foo"
 +
 +when (thingy) {
 +  "foo", "goo" -> println("something")
 +  "bar", "baz", "frobozz" -> println("something else")
 +  else -> println("and now for something completely different")
 +}
 +</code>
 +
 +For numbers, you can use ''..'' syntax and in to set up a “range” and test against it:
 +<code kotlin>
 +val i = 3
 +
 +when (i) {
 +  in 3..10 -> println("something")
 +  in 1..2 -> println("something else")
 +  else -> println("and now for something completely different")
 +}
 +</code>
 +However, these simplifications only work when you supply a value to ''when'', as opposed to leaving ''when'' empty and using boolean expressions for the branches.
 +
 +The value for comparison does not need to be a constant — any expression will also work:
 +<code kotlin>
 +val thingy = "bar"
 +val otherThingy = "BAR"
 +
 +when (thingy) {
 +  "foo", "goo" -> println("something")
 +  otherThingy.toLowerCase() -> println("something else")
 +  else -> println("and now for something completely different")
 +}
 +</code>
 +
 +
 +
 +
 +==== While ====
 +
 +<code kotlin>
 +var i = 0
 +
 +while (i < 10) {
 +  i++
 +  println(i)
 +}
 +</code>
 +
 +However, ''while'' is not as common in Kotlin as it is in other languages. More often we use operations on collections (e.g., ''forEach()'') rather than while. 
 +==== If/When As Expressions ====
 +Kotlin lacks ternary support, but more than makes up for it by allowing if to serve in the same role:
 +<code kotlin>
 +val i = 3
 +
 +val j = if(i < 2) 2 else i
 +</code>
 +
 +Also possible with braces:
 +<code kotlin>
 +val bar = 5
 +val foo = if (bar > 10) {
 +  10
 +}
 +else {
 +  bar
 +}
 +
 +println(foo)
 +</code>
 +The value of the last statement of the block is what that block evaluates to. In this case, each of those blocks is a single statement, but if we had several statements in a block, while they are all executed, the value from the last statement is used for the result (assuming that block is used, based on the conditional expression).
 +
 +''when'' can also be used as an expression:
 +<code kotlin>
 +val i = 3
 +
 +val message = when (i) {
 +  in 3..10 -> "something"
 +  in 1..2 -> "something else"
 +  else -> "and now for something completely different"
 +}
 +
 +println(message)
 +</code>
 +
 +In the situations, when ''if'' or ''when'' is used as expression, they must be exhaustive (the expression should work for all cases!). If you try a non-exhaustive ''if'' or ''when'' for an expression, such as:
 +<code kotlin>
 +val i = 3
 +
 +val message = when (i) {
 +  in 3..10 -> "something"
 +  in 1..2 -> 5
 +}
 +
 +println(message)
 +</code>
 +…you will get a compiler error. Because it is not clear what should be done in ''else'' case.
 +
 +
 +==== Bustin’ Out ====
 +
 +You can always use return to exit the entire function that you are in. Beyond that, though, there are two loop control statements that you can use: ''break'' and ''continue''. These work much like their counterparts in Java and other programming languages.
 +
 +  * ''break'' says “abandon the loop”
 +  * ''continue'' says “skip the rest of this pass through the loop, and move along to the next pass through the loop”
 +
 +===== Basic Classes =====
 +
 +====Basic Classes====
 +A class does not have to contain any of that — this is a valid Kotlin class definition:
 +<code kotlin>
 +class Foo {
 +  
 +}
 +</code>
 +
 +This is also valid:
 +<code kotlin>
 +class Foo
 +</code>
 +
 +Having a class with no body seems odd. However, in Kotlin, you will occasionally see that sort of thing, particularly with data classes and sealed classes. However, most ordinary classes will have properties and functions.
 +
 +====Creating Instances of Classes====
 +
 +To create an instance of a class it is not necessary to use ''new()'' like in Java. Simply call the class like function:
 +
 +<code kotlin>
 +class Foo
 +
 +fun main() {
 +  val foo = Foo()
 +
 +  println(foo)
 +}
 +</code>
 +====Packages====
 +The syntax to declare package is Java-like: 
 +
 +<code kotlin>
 +package bar.goo
 +
 +class Foo
 +
 +val foo = Foo()
 +
 +</code>
 +====Common Contents====
 +
 +=== Functions ===
 +<code kotlin>
 +class Foo {
 +  fun something() {
 +    println("Hello, world!")
 +  }
 +}
 +
 +fun main() {
 +  val foo = Foo()
 +
 +  foo.something()
 +}
 +</code>
 +
 +=== Properties ===
 +Classes can also have properties:
 +<code kotlin>
 +class Foo {
 +  var count = 0
 +
 +  fun something() {
 +    count += 1
 +    println("something() was called $count times")
 +  }
 +}
 +
 +fun main() {
 +  val foo = Foo()
 +
 +  foo.something()
 +  foo.something()
 +  foo.something()
 +
 +  println("the final count was ${foo.count}")
 +}
 +</code>
 +====this====
 +
 +As with Java, Kotlin uses this as a pseudo-property to refer to the instance of the object in whose function you happen to be running.
 +
 +<code kotlin>
 +class Foo {
 +  var count = 0
 +
 +  fun something() {
 +    this.count += 1
 +    println("something() was called $count times")
 +  }
 +}
 +</code>
 +
 +
 +====Constructors====
 +
 +The way you will normally see Kotlin classes have a constructor is by making the actual class name itself take the constructor parameters:
 +<code kotlin>
 +class Foo(var count: Int) {
 +  fun something() {
 +    count += 1
 +    println("something() was called $count times")
 +  }
 +}
 +
 +fun main() {
 +  val foo = Foo(0)
 +
 +  foo.something()
 +  foo.something()
 +  foo.something()
 +
 +  println("the final count was ${foo.count}")
 +}
 +</code>
 +
 +The constructor syntax shown above is really a shorthand for using the constructor keyword:
 +<code kotlin>
 +class Foo constructor(var count: Int) {
 +  fun something() {
 +    count += 1
 +    println("something() was called $count times")
 +  }
 +}
 +// ...
 +</code>
 +
 +=== Init Blocks ===
 +
 +Syntax-wise, an init block resembles a Java static block: a set of braces-wrapped statements preceded by a keyword. In Java, the static block is executed once for the class and is used to initialize complex static fields. In Kotlin, an init block is executed //once for each instance// and serves as a baseline constructor body:
 +<code kotlin>
 +class Foo(val sillyCount: String) {
 +  var count = 0
 +
 +  init {
 +    count = sillyCount.toInt()
 +  }
 +
 +  fun something() {
 +    count += 1
 +    println("something() was not called $count times")
 +  }
 +}
 +
 +
 +fun main() {
 +  val foo = Foo("7")
 +
 +  foo.something()
 +  foo.something()
 +  foo.something()
 +
 +  println("the final count was ${foo.count}")
 +}
 +</code>
 +
 +''init'' blocks have a couple of other distinctions, particularly when compared to Java/Ruby constructors:
 +
 +  * You can have more than one ''init'' block. They are executed in the order that they appear in the class.
 +  * An ''init'' block can only reference properties that are declared before it in the class, not ones declared after it. As a result, an ''init'' block often appears after the list of properties, so the ''init'' block can reference any of the properties.
 +  * Sometimes, you will see constructor parameters that do not have the ''var'' or ''val'' keyword. They just have the parameter name and type. They are still constructor parameters, but they are not properties. You cannot refer to them from the functions of your class. You can refer to them from ''init'' blocks, though.
 +
 +=== Having Multiple Constructors ===
 +The primary constructor appears in the class declaration itself, as we have seen. Other constructors, if they exist, are called “secondary constructors”, and they somewhat resemble ordinary functions:
 +<code kotlin>
 +class Foo(var count: Int) {
 +
 +  constructor(sillyCount: String) : this(sillyCount.toInt()) {
 +    // could have code here if needed
 +  }
 +
 +  fun something() {
 +    count += 1
 +    println("something() was not called $count times")
 +  }
 +}
 +
 +
 +fun main() {
 +  val foo = Foo("7")
 +
 +  foo.something()
 +  foo.something()
 +  foo.something()
 +
 +  println("the final count was ${foo.count}")
 +}
 +</code>
 +A primary constructor has no function body — any such code goes into an ''init'' block. Secondary constructors, though, can have bodies, the way that functions do, but only if needed.
 +
 +Secondary constructors //must// arrange to //call the primary constructor//. This is handled by having a this() call after the constructor parameter list, separated from that list via a colon. The ''this()'' call needs to match the parameter list of the primary constructor — in the example shown above, the secondary constructor needs to provide a Int to the primary constructor.
 +
 +=== Default Parameter Values ===
 +Kotlin supports default parameter values in constructors:
 +<code kotlin>
 +
 +
 +class View(
 +  context: Context,
 +  attrs: AttributeSet? = null,
 +  defStyleAttr: Int = 0,
 +  defStyleRes: Int = 0
 +) {
 +  // two tons of code
 +}
 +</code>
 +
 +Here, the latter three parameters all have default values defined, giving us the ability to call the constructor with one parameter, all four parameters, or combinations in between.
 +====Inheritance====
 +Kotlin uses colons to indicate inheritance:
 +<code kotlin>
 +class Foo(var count: Int) : Any() {
 +  fun something() {
 +    count += 1
 +    println("something() was called $count times")
 +  }
 +}
 +</code>
 +
 +(the Java counterpart is the keyword ''extends'')
 +
 +Chaining the super class contructor:
 +<code kotlin>
 +open class Base(val tag: String)
 +
 +class Foo(var count: Int) : Base("Foo Example") {
 +  fun something() {
 +    count += 1
 +    println("$tag: something() was called $count times")
 +  }
 +}
 +</code>
 +
 +In Java, by default, any class can be extended by a subclass. To prevent a class from being extended, you have to mark it as ''final''.
 +
 +Kotlin goes the opposite route. Kotlin classes //cannot be extended by default//. You have to mark classes that can be extended using ''open''. Failure to do that results in an error.
 +
 +=== Overriding Functions ===
 +  * A subclass can call functions that it inherits from its superclass.
 +  * A subclass can override functions of its superclasses… at least, if those too are marked as ''open''.
 +
 +<code kotlin>
 +open class Base(val tag: String) {
 +  open fun gimmeTheTag() = tag
 +}
 +
 +class Foo(var count: Int) : Base("Foo Example") {
 +  override fun gimmeTheTag() = "Not the Original Tag"
 +
 +  fun something() {
 +    count += 1
 +    println("${gimmeTheTag()}: something() was called $count times")
 +  }
 +}
 +</code>
 +  * By default, ''open'' is transitive. Once a function is marked as open, it is open for all subclasses down the hierarchy, regardless of whether intervening classes override the function or not.
 +    * unless the class which overrides the functions marks its version of that function as ''final''
 +
 +=== Overriding Properties ===
 +It is also possible for a class to declare a property as ''open'', allowing subclasses to override it.
 +<code kotlin>
 +open class Base(open val tag: String) {
 +  open fun gimmeTheTag() = tag
 +}
 +
 +open class Intermezzo(override val tag: String) : Base(tag)
 +
 +class Foo(var count: Int) : Intermezzo("Foo Example") {
 +  override fun gimmeTheTag() = "Not the Original Tag"
 +
 +  fun something() {
 +    count += 1
 +    println("${gimmeTheTag()}: something() was called $count times")
 +  }
 +}
 +</code>
 +
 +=== Chaining to Superclass Functions ===
 +
 +<code kotlin>
 +open class Base(val tag: String) {
 +  open fun gimmeTheTag() = tag
 +}
 +
 +class Foo(var count: Int) : Base("Foo Example") {
 +  override fun gimmeTheTag() = super.gimmeTheTag() + "-Extended"
 +
 +  fun something() {
 +    count += 1
 +    println("${gimmeTheTag()}: something() was called $count times")
 +  }
 +}
 +</code>
 +
 +=== Inheritance Tests ===
 +Kotlin has syntax similar to Java's ''instanceof'' , with a shorter keyword: ''is''. So, we can do this:
 +<code kotlin>
 +open class Animal
 +
 +class Frog : Animal()
 +
 +class Axolotl : Animal()
 +
 +fun main() {
 +  val critter: Animal = Frog()
 +
 +  if (critter is Frog) println("Ribbit!") else println("Ummm... whatever noise an axolotl makes!")
 +}
 +</code>
 +In Kotlin, we can use is not only as part of an expression, but we can use it as a test for a when clause. We can rewrite the previous example using a when:
 +<code kotlin>
 +open class Animal
 +
 +class Frog : Animal()
 +
 +class Axolotl : Animal()
 +
 +fun main() {
 +  val critter: Animal = Frog()
 +
 +  when (critter) {
 +    is Frog -> println("Ribbit!")
 +    else -> println("Ummm... whatever noise an axolotl makes!")
 +  }
 +}
 +</code>
 +
 +=== Casting ===
 +In Kotlin, casting is performed by using the ''as'' keyword:
 +<code kotlin>
 +val critter: Animal = Frog()
 +val kermit = critter as Frog
 +</code>
 +
 +Inside of ''if'' and ''when'' blocks, if we know that a variable is really of some subtype, the compiler lets us skip the casts and allows us to refer to the variable as the subtype, even though it was declared as a supertype.
 +<code kotlin>
 +open class Animal
 +
 +class Frog : Animal() {
 +  fun hop() = println("Hop!")
 +}
 +
 +class Axolotl : Animal() {
 +  fun swim() = println("Swish!")
 +}
 +
 +fun main() {
 +  val critter: Animal = Frog()
 +
 +  when (critter) {
 +    is Frog -> critter.hop()
 +    is Axolotl -> critter.swim()
 +  }
 +}
 +</code>
 +
 +In a Java-style world, this would not compile. critter is an Animal, and Animal has neither hop() nor swim(). However, Kotlin realizes that the is Frog code will only be executed if critter is a Frog, so it allows us to call hop() on critter, as if critter were declared as a Frog instead of as an Animal. Similarly, we can call swim() on critter if it is Axolotl.
 +
 +But this works only if compiler is sure. This code will not compile, because it is unclear in ''else'' whether critter is really ''Axolotl'':
 +<code kotlin>
 +//...
 +when (critter) {
 +  is Frog -> critter.hop()
 +  else -> critter.swim()
 +}
 +//...
 +</code>
 + 
 +
 +
 +
 +
 +===== Comments and Documentation =====
 +==== Basic Comment Syntax ====
 +All is like in Java. With one exception:
 +
 +The biggest — and perhaps only — difference between Kotlin comments and what you might do in Java is that multi-line comments can be nested in Kotlin. 
 +
 +==== Introducing KDoc ====
 +
 +Kotlin’s equivalent to JavaDoc is KDoc.
 +
 +Where KDoc breaks from JavaDoc is in terms of text formatting. KDoc uses [[https://en.wikipedia.org/wiki/Markdown|Markdown]].
 +
 +What Markdown lacks is a way to link to things inside the same document. KDoc extends Markdown linking syntax, allowing you to reference properties, functions, and similar named things by using simple bracket syntax:
 +<code kotlin>
 +/**
 + * This is the summary of your Kotlin class. It should explain, in a single
 + * paragraph, the role of this class in your project.
 + *
 + * This class has a single function: [something].
 + *
 + * You can also link to other classes, such as [kotlin.String], using the
 + * fully-qualified class name.
 + *
 + * And, of course, you can [link to external content](https://commonsware.com).
 + */
 +</code>
 +
 +As with JavaDoc, KDoc supports “block tags” for documenting sub-elements of class, function, etc. For example, you can use @param to document a function parameter, @return to document a function return value, and so forth.
 +
 +Just as Java has a javadoc program to generate JavaDocs, Kotlin has a similar tool: [[https://github.com/Kotlin/dokka|Dokka]].
 +
 +
 +
 +
 +===== Properties =====
 +==== Initialization ====
 +
 +Properties need to be initialized at some point. 
 +
 +Initialization when declared (''count''):
 +<code kotlin>
 +class Foo(sillyCount: String) {
 +  var count = sillyCount.toInt()
 +
 +  fun something() {
 +    count += 1
 +    println("something() was not called $count times")
 +  }
 +}
 +</code>
 +
 +In an ''init'' block:
 +<code kotlin>
 +class Foo(sillyCount: String) {
 +  var count: Int
 +
 +  init {
 +    count = sillyCount.toInt()
 +  }
 +  // ...
 +}
 +</code>
 +
 +Initialization "sometime later":
 +<code kotlin>
 +class Foo {
 +  var count = 0
 +  lateinit var label: String
 +
 +  fun defineTag(tag: String) {
 +    label = tag
 +  }
 +
 +  fun something() {
 +    count += 1
 +    println("$label: something() was called $count times")
 +  }
 +}
 +</code>
 +
 +But in this case the function ''something()'' must be called after ''defineTag()''. Where possible, you should try to avoid ''lateinit'', as it is easy to make mistakes and try using the ''lateinit'' property before it is initialized.
 +
 +Also note that ''lateinit'' cannot be used for types based on primitives, so you cannot have a ''lateinit'' ''Int'', ''Boolean'', etc.
 +
 +Yet another possibility is to use ''by lazy'':
 +<code kotlin>
 +class Foo(val rawLabel: String) {
 +  var count = 0
 +  val label: String by lazy { println("initializing via lazy!"); rawLabel.toUpperCase() }
 +
 +  fun something() {
 +    count += 1
 +    println("$label: something() was called $count times")
 +  }
 +}
 +</code>
 +
 +Here, ''label'' is initialized lazily. Whenever we first attempt to use ''label'', the lambda expression will be executed, and that value is what we see as the value of ''label''.
 +
 +One more way to initialize property is to use a function like property. In Kotlin it is possible to call function without parethesis (e.g. ''forEach''). Such functions are named "fake properties". They will be discussed later in this book.
 +==== Constants ====
 +
 +Kotlin has a ''const'' keyword, which you can use to declare certain ''val'' properties as constants. This is somewhat reminiscent of ''final'' in Java. ''val'' is already a constant but there are some cases for using ''const'' in Kotlin. These cases will be discussed later.
 +==== Getting Down in the Weeds ====
 +
 +A Kotlin property really represents the combination of these three elements:
 +  * a field
 +  * a getter function
 +  * a setter function
 +
 +It is something like JavaBeans, but without the need to implement standard getter and setter.
 +
 +Some advanced Kotlin syntax — such as the “fake properties” alluded to earlier — take advantage of this, overriding the default getter and/or setter to do something else. But in the most cases the standard is enough.
 +
 +
 +
 +===== Visibility and Scope =====
 +
 +  * Visibility: What is allowed to see these classes, functions, and properties?
 +  * Scope: Where do these classes, functions, and properties actually exist?
 +
 +
 +==== Visibility ====
 +
 +  * ''public''
 +    * Kotlin takes the public-by-default route. Everything that is defined by default is visible to anything else.
 +  * ''private''
 +    * ''private'' limits access to instances of its class, and nothing else.
 +    * ''private'' is not just available for aspects of classes. Classes themselves can be private. Properties and functions defined outside of classes can also be marked as ''private''. In these cases, the determination of what can and cannot access the private items is based on the file:
 +      * ''private'' top-level things are visible to other things in the same Kotlin source file
 +      * ''private'' top-level things are inaccessible to other things in other Kotlin files
 +
 +  * ''protected''
 +    * The ''protected'' visibility modifier works a lot like ''private'', but it also allows subclasses to access the property or function.
 +    * ''protected'' is defined as “accessible by this class and its subclasses”, so it only makes sense in the context of classes
 +
 +  * ''package''
 +    * Kotlin **does not offer package-private visibility**. 
 +
 +  * ''internal''
 +    * anything marked as ''internal'' is visible to code in the same module but is not visible to code in other modules.
 +      * strange -> the meaning of the "module" depends on the context in which project is used
 +    * So, if you plan on publishing some form of Kotlin library, ''internal'' will be important. 
 +      * On a large project that you have divided into modules, ''internal'' can be useful. 
 +      * For small single-module projects, ''internal'' is pointless.
 +==== Scope ====
 +
 +  * Global
 +    * Top-level definitions in a Kotlin source file are global in scope. 
 +    * Immutable globals — classes, ''val'', etc. — will exist for the life of the process that is executing the Kotlin code. 
 +    * Mutable globals — such as ''var'' — have references that will live forever, but the objects that those references reference might come and go as the value of that reference changes.
 +
 +  * Instance
 +    * Properties defined inside of a class have “instance” scope. Each instance of the enclosing class will have its own set of instance properties, independent of any other instance of that same class.
 +
 +  * Local
 +    * Local to Functions
 +    * Local to Blocks/Lambdas
 +===== Abstract Classes and Interfaces =====
 +
 +  * -> https://commonsware.com/Kotlin/pages/chap-interface-001
 +
 +
 +==== The Objective: Contracts ====
 +
 +==== Abstract Classes ====
 +
 +==== Interfaces ====
 +
 +==== Which Do You Use? ====
 +
 +
 +===== Data Class =====
 +===== The object Keyword =====
 +===== Nested Objects and Classes =====
 +===== Enums and Sealed Classes =====
 +===== Generics =====
 +===== Exceptions =====
 +===== Annotations =====
 +===== Nullability =====
 +===== Scope Functions =====
 +===== Functional Programming =====
 +===== Extension Functions =====
 +===== Java Interoperability =====
 +===== Changes in Newer Kotlin Versions =====
 +===== Custom Accessors =====
 +===== Extension Properties =====
 +===== Escaping Keywords =====
 +===== Escaped Method Names =====
 +===== Property Delegates =====
 +===== Class Delegation =====
 +===== Constants =====
 +===== Abstract Properties =====
 +===== Covariance in Generics =====
 +===== Contravariance in Generics =====
 +===== Anonymous Functions =====
 +===== Local Functions =====
 +===== Local Types =====
 +===== Inline Functions =====
 +===== Inline Classes =====
 +===== Reified Type Parameters =====
 +===== noinline and crossinline =====
 +===== Receivers in Function Types =====
 +===== Renamed Imports =====
 +===== Operator Overloading =====
 +===== Infix Functions =====
 +===== Destructuring Declarations =====
 +===== Labeled Returns =====
 +===== Nothing =====
 +===== Types of Keywords =====