1.47M
Category: programmingprogramming

Основы Kotlin

1.

Гречнев Антон
Основы Kotlin

2.

Класс Any
Является супер-классов для всех классов (неявно)
fun toString(): String
println(Any().toString())
fun hashCode(): Int
println(Any().hashCode())
Аргументы
функции неизменяемые. Им нельзя установить
новые значения.
fun equals(other: Any?): Boolean
java.lang.Object@27bc2616
666641942
println(Any().equals(Any())) false

3.

Kotlin vs Java
public open class Any {
public class Object {
public final Class<?> getClass()
public int hashCode()
public boolean equals(java.lang.Object obj)
public String toString()
protected java.lang.Object clone()
public final native void notify()
public final native void notifyAll()
public final void wait(long timeoutMillis)
public final native void wait(long timeoutMillis, int nanos)
public final void wait()
protected void finalize()
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
}
}

4.

equals
Рефлексивность
x.equals(x) == true
Для любого заданного значения x,
выражение x.equals(x) должно
возвращать true при x != null
Симметричность
если
x.equals(y) == true
то
y.equals(x) == true
Для любых заданных
значений x и y, x.equals(y) должно
возвращать true только в том случае,
когда y.equals(x) возвращает true.
Транзитивность
если
x.equals(y) == true
x.equals(z) == true
то
y.equals(z) == true
Для любых заданных
значений x, y и z,
если x.equals(y) возвращает true и y.e
quals(z) возвращает true, x.equals(z) д
олжно вернуть значение true.
Сравнение null
x.equals(null) == false
Для любого заданного
значения x вызов x.equals(null) долже
н возвращать false.

5.

hashСode
• Если два объекта равны по equals, их хэш-коды должны
быть одинаковыми.
• Хэш-код должен оставаться неизменным для одного
объекта, пока его значимые данные остаются теми же
самыми.
• Чем меньше вероятность коллизий (совпадений хэшкодов разных объектов), тем эффективнее работают
коллекции.

6.

Контракт
equals и
hashcode
1) Вызов hashCode для одного и того же объекта
должен возвращать одинаковые хеш-значения
2) Если equals() для двух объектов возвращает true,
hashCode() также должен возвращать для них одно и
то же число.
При этом неравные между собой объекты могут иметь
одинаковый hashCode
val object = Object()
println(object.hashcode())
println(object.hashcode())
значение

вернет
то
же
val object = Object()
val object2 = object
println(object.equals(object2)) – если true
println(object.hashcode() == object2.hashcode()) –
будет true

7.

Пакеты и импорты
// Объявление пакета вверху файла
package com.example.myapp
Структура каталогов:
src/
com/
class MyClass {
example/
// ... код функции
класса ... неизменяемые. Им нельзя установить новые
myapp/
Аргументы
значения.
}
MyClass.kt

8.

Пакеты и импорты
import java.util.ArrayList
import java.lang.OutOfMemoryError
// нет импортов
fun importTest() {
fun importTest() {
val list = java.util.ArrayList<String>()
val list = ArrayList<String>()
val list2 = java.util.ArrayList<String>()
val list2 =функции
ArrayList<String>()
throw java.lang.OutOfMemoryError()
Аргументы
неизменяемые. Им нельзя установить новые
значения.
throw OutOfMemoryError()
}
}

9.

1. Импорт одного конкретного класса.
import java.util.ArrayList;
2. Импорт всех классов из указанного пакета.
import java.util.*;
Импорты
Типы
3. Автоматический импорт или импорт по-умолчанию
kotlin.*
kotlin.collections.*
4. Импорт функций и свойств (в том числе и статических)
import kotlin.Int.Companion.MAX_VALUE
import kotlinx.coroutines.launch

10.

Импорты
Тонкости
• Конфликты имен: если два класса с одинаковым
именем находятся в разных пакетах и вы хотите
использовать оба класса в одном файле, вы
должны использовать полное имя класса для
одного из них, чтобы избежать конфликта
• Импорты и компиляция: Импорты не влияют на
размер исполняемого файла (.class). Они только
упрощают написание и чтение исходного кода
• Порядок импортов: Импорты обычно
размещаются в верхней части файла, после
объявления пакета (package).

11.

Исключения
Иерархия
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: Index 3
out of bounds for length 2
at java.util.Arrays$ArrayList.get (:-1)
Выполняем код: пытаемся взять третий
элемент в списке размера два элемента
Получаем остановку приложения и описание ошибки в
консоли

12.

Обработка исключений
Чтобы обработать исключение нужно использовать конструкцию
try-catch-finally

13.

Исключения
Иерархия

14.

Исключения
Иерархия
— обработает всех наследников указанного в скобках класса-исключения

15.

Исключения
Выражения
В отличии от JAVA

16.

Тип Nothing

17.

companion object и object
Вспомогательные объекты
Объявление объекта внутри класса может
быть
отмечено
ключевым
словом
companion object
Объявлением объекта
Всегда имеет приставку в виде ключевого
слова object
class MyClass {
companion object {
val TEST = "test"
}
}
val myCompanion = MyClass.Companion.TEST
object MyObject {
fun doSmth(){}
}
class MyClass {
companion object MyObejct {}
}
val myCompanion = MyClass.MyObejct
val myObject = MyObject
myObject.doSmth()
public static final MyObject INSTANCE = new MyObject();

18.

Data class
Получили
data class User(val name: String, val age: Int) {
fun component1(): String = this.name
fun component2(): Int = this.age
fun copy(name: String, age: Int) : User = User(name, age)
fun toString() = "User(name=" + this.name + ", age=" + thi
fun hashCode(): Int {
Объявили
var result = this.name.hashCode();
data class User(val name: String, val age:
result = result * 31 + Integer.hashCode(this.age);
Int)
return result;
}
Аргументы функции неизменяемые. Им нельзя установить новые
значения. Any): Boolean {
fun equals(other:
if (this == other) { return true }
else if (other !is User) { return false } else {
if (this.name != other.name) { return false }
else { return this.age == other.age } }
}
}

19.

enum class Direction {
NORTH, SOUTH, WEST, EAST
}
Enum class
EnumClass.valueOf(value: String): EnumClass
EnumClass.values(): Array<EnumClass>
val name: String
val ordinal: Int
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}

20.

sealed class
sealed interface Error {
sealed class IOError(): Error {
class FileReadError(val file: File): IOError()
class DatabaseError(): IOError()
}
object RuntimeError : Error
}
fun log(e: Error) = when(e) {
is FileReadError -> { println("Error while reading file
${e.file}") }
is DatabaseError -> { println("Error while reading from
database ${e.source}") }
is RuntimeError -> { println("Runtime error")
}

21.

enum vs sealed
Тонкости
enum class Status(
val message: String? = null,
val error: String? = null
){
SUCCESS(message = "Ура! Успех"),
ERROR(error = "Произошла ошибка"),
LOADING()
}
sealed class Status {
data class Success(val message: String) : Status()
data class Error(val error: String) : Status()
data class Loading() : Status()
}

22.

enum vs sealed
Тонкости
1. Конечный набор констант
2. Методы перечисления значений
3. Есть порядок
4. Есть имя
5. По-умолчанию
Comparable
Serializable
и
1. Иерархическая структура
2. Разное кол-во параметров для
разных наследников
3. Есть
возможность
наследования
других классов
4. Создание
с
динамическими
свойствами

23.

Функции
fun myFunction(param1: String, param2: Int) : Unit {
// код функции
return
}
Аргументы по умолчанию
fun myFunction(param1: String = “test”, param2: Int = 100)
Именованные аргументы в месте вызова
myFunction(param1 = “test2”, param2 = 101)

24.

Функции
Область видимости
myFunction()
param1 : String
param2 : Int
val i = innerFunction(
other = “someString”)
innerFunction
other : String
fun myFunction(param1: String, param2: Int) {
val i = innerFunction(other = “someString”)
}
fun innerFunction(other: String) {
// что-то делаем внутри
}

25.

Функциональные типы
(A, B) -> C
Лямбды
Функции высшего
порядка
(Int) -> String
((Int, Int) -> Int)?
val onClick: () -> Unit = { … }
val intToString: (i: Int) -> String = { i -> i.toString() }
intToString.invoke(1)
intToString(1)
val a = fun(i:Int) : String { i: Int -> i.toString() }
тоже самое
val a = { i: Int -> i.toString() }
ints.filter { it > 0 }
// этот литерал имеет тип '(it: Int) -> Boolean'

26.

Пример ламбда функции
fun applyLambda(text : String, transform : (String) -> String) : String {

}
fun applyLambda(text : String, transform : (String) -> String) : String {
return transform.invoke(text)
}
applyLambda(text = “text”, transform = { t -> t.uppercase() })
applyLambda(text = “text”) { it.uppercase() }

27.

fun <T> List<T>.lastIndex() = size - 1
val <T> List<T>.lastIndex: Int
get() = size - 1
Расширения
Extensions
val list = listOf(“a”, “b”, ”c”)
list.lastIndex()
или
list.lastIndex
fun String.lastSymbol() = this[this.length - 1]
В JAVA
public static fun lastSymbol(str: String) {
return str[str.length – 1]
}

28.

lateinit
синтаксический сахар
var o: Pair<String, String>? = null
lateinit var o : Pair<String, String>
fun test() {
fun test() {
o.first on a nullable receiver of
o.first Only safe (?.) or non-null asserted (!!.) calls are allowed
}
type 'kotlin. Pair<kotlin. String, kotlin. String>?'}
Аргументы функции неизменяемые. Им нельзя установить новые значения.
fun test() {
val first = o?.first
if (first != null) {
// если не null
} else {
// если null
}
}
public static final String getO() {
String var0 = o;
if (var0 != null) {
return var0;
} else {
Intrinsics.throwUninitializedPropertyAccessException(”o");
}
}

29.

lateinit
• Альтернатива для ?. или !!
• Нельзя применять к примитивным типам (Int, Boolean…)
• Использовать только при понимании порядка объявление
и вызова переменной
• Ошибки можно отследить только в runtime

30.

lazy
синтаксический сахар
class
class A
A {{
val
val bigString:
bigString: String
String =byparseSuperBigString()
lazy { parseSuperBigString() }
get() = parseSuperBigString()
fun
fun useString()
useString() {{
funprintln("Здесь
useString() { используем
println("Здесь
используем строку
строку $bigString")
$bigString")
}} println("Здесь используем строку $bigString")
}
fun
fun use2String()
use2String() {{
println("Здесь
println("Здесь используем
используем строку
строку повторно
повторно $bigString")
$bigString")
}}
fun doNotUseString() {
fun
doNotUseString()
{{
не используем
строку")
funprintln("Здесь
doNotUseString()
} println("Здесь
println("Здесь не
не используем
используем строку")
строку")
} }}
}}
English     Русский Rules