Download - Kotlin

Transcript
Page 1: Kotlin

KotlinКогда уже закончиться какой-то год 2006* ?

* год выхода Java SE 6

Page 2: Kotlin

Какова жизнь с Java 6?

• Нельзя добавить методы для типов, определенных платформой либо сторонней библиотекой

• Распространенность java.lang.NullPointerException

• Android поддерживает только Java 6 ** есть небольшой функционал от Java 7

• Нет Stream API для коллекций

Page 3: Kotlin

Что вы получите при использовании Kotlin?

• Полная интероперабельность с Java• Null-Safety• Ссылки на методы, замыкания (closure)• Лямбды из коробки• Немодифицируемые коллекции

Page 4: Kotlin

Переменные

• val sample: String = "Sample String”• var sample = "Sample String"

var sample: List<String> = ArrayList()

Page 5: Kotlin

NULL• В Kotlin необходимо явно указывать - может ли

переменная принимать null

• Nullable переменные должны быть промаркированы знаком вопрос “?” после типа, т.е.:

val name : String? = null

• Можно присвоить значение от not-nullable типа в nullable без каки либо проблем :

fun main(args: Array<String>) { val firstName: String = "Adam" // not nullable val name : String? = firstName // nullable}

Page 6: Kotlin

• В противном случае необходимо явно декларировать, что nullable переменная не содержит null. Это достигается с помощью оператора двойного восклицания “!!” (который указывает: “Я точно уверен, что эта переменная не содержит null”)

fun main(args: Array<String>) { val name: String? = "Adam" val firstName: String = name!! print("$firstName")}

Page 7: Kotlin

Классы

Page 8: Kotlin

public class Student {

private int course; private String name; private final Date birthday;

public Student(int course, @NotNull String name, @NotNull Date birthday) { this.course = course; this.name = name; this.birthday = birthday; }

public int getCourse() { return course; } public void setCourse(int course) { this.course = course; } @NotNull public String getName() { return name; } public void setName(@NotNull String name) { this.name = name; } @NotNull public Date getBirthday() { return birthday; }

@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return course == student.course && name.equals(student.name) && birthday.equals(student.birthday); } @Override public int hashCode() { int result = course; result = 31 * result + name.hashCode(); result = 31 * result + birthday.hashCode(); return result; }}

Page 9: Kotlin

class Student(var course: Int, var name: String, val birthday: Date) {

override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as Student return course == other.course && name == other.name && birthday != other.birthday }

override fun hashCode(): Int { var result = course result += 31 * result + name.hashCode() result += 31 * result + birthday.hashCode() return result }}

Page 10: Kotlin

data class Student( var course: Int, var name: String, var birthday: Date)

Generate methods:1. toString2. equals / hashCode3. componentN4. copy

Page 11: Kotlin

Однострочные ф-ии• Это сокращенная форма определения функции, когда

у вас есть только одно выражение, которое будет выполнено.Необходимо заметить, что нет необходимости явно указывать возвращаемый тип:

fun main(args: Array<String>) { val res = add(1, 1) p(“$res") println(englishGreeting())}

fun englishGreeting() : String = "Hello world"fun add(a: Int, b: Int) = a + bfun isValueMore(value : Int) = if (value > 0) 1 else -1

Page 12: Kotlin

Порядок аргументов

• Котлин позволяет указывать параметры по-умолчанию, делая их не обязательными:

fun main(args : Array<String>) { greet(firstName = "Frasensco", lastName = "Merini") greet(lastName = "John", firstName = "Stamos") greet("Borat", "Ismail") greet("Crystal", lastName = "Stamos") call("Xavier", age = 20, location = "Portugal")}

fun greet(firstName : String, lastName : String){ println("Good morning $firstName $lastName")}

fun call(name : String, location : String, age : Int){ println("Call $name who lives at $location and he is $age old")}

Page 13: Kotlin

А теперь реально крутые вещи

Page 14: Kotlin

Destructuring Declarations

Представляет собой возможность разложить объект на составляющие:

data class Report(val name: String, val date: Long)

fun loadReport(uuid: String) { api.getReport(uuid) { (name, date) -> reportView.text = name dateView.text = formatDate(date) }}

или в Map

for ((key, value) in map) { println("Good morning $value")

}

Page 15: Kotlin

When• В Java сравнение (if, switch) может работать с : byte, short, char, int.

Также можно использовать Enum и String (начиная с JDK7), и специальные классы, которые являются обёрткой для примитивных типов: Character, Byte, Short, Integer

• В Kotlin можно работать с большим количеством классов, проверять на принадлежность, сравнивать с выражениями, узнавать попадение в диапозон и т.д.:

return when (value) { "color" -> "Color" is String -> "String" is Int -> “Integer" 1 + 2 -> "3" value == 12 -> “twelve" in 1..10 ->"x is in the range" in validNumbers ->"x is valid" !in 10..20 ->"x is outside the range" else -> throw IllegalArgumentException("Invalid param value")}

Page 16: Kotlin

Lambdasreturn parsedContacts .filter { it.name != null && it.image != null } .sortedBy { it.name } .map { Contact(it.id, it.name!!, it.image!!) }

val positives = list.filter { x -> x > 0 }

или короче

val positives = list.filter { it > 0 }

Page 17: Kotlin

String Templates

val student = Student(1, "Ivan Ivanov", Date())

println("Student '${student.name}' is on ${student.course} course.")

Page 18: Kotlin

Delegated propertiesclass Foo { private var text: String? = null

private fun computeText(): String { … }

fun getText(): String { if (text == null) { text = computeText() } return text!! }}

Page 19: Kotlin

Delegated properties

class Foo { val text: String by lazy { computeText() } private fun computeText(): String { … }}

Page 20: Kotlin

Delegated properties

class SampleFragment : Fragment() { val margin: Int by lazy { resources.getDimensionPixelSize(R.dimen.std_margin) }}

Page 21: Kotlin

Callable references*привет Java 8

• Что делать, если у Вас уже есть ф-ия которую вы хотите передать как параметр ? Просто необходимо добавить префикс “::”

fun main(args: Array<String>) { calcAndShow(10, 10, ::add) //20 calcAndShow(10, 10, ::multiply) // 100 calcAndShow(10, 19, { x, y -> x - y }) //-9}

fun calcAndShow(a: Int, b: Int, func: (a: Int, b: Int) -> Int) { val result = func(a, b) println("$result")}

fun add(a: Int, b: Int): Int = a + bfun multiply(a: Int, b: Int): Int = a * b

Page 22: Kotlin

Extension function• Эти функции предоставляют возможность расширить класс

с новыми функциональными возможностями, не наследуясь от класса или используя любой тип шаблона проектирования, таких как Decorator.

fun Int.show(){ println("This number is $this")}

fun main(args : Array<String>){ 3.show()}

fun <T: Parcelable> T.toJson(): String{ ...}

Page 23: Kotlin

fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { Toast.makeText(this, message, duration).show();}

fun ImageView.loadUrl(url: String) { Picasso.with(context).load(url).into(this)}

fun test(actvitiy: Activity){ val image = ImageView(actvitiy) image.loadUrl("http://....") actvitiy.toast(“hello")}

Page 24: Kotlin

Extension function expression

fun SQLiteDatabase.trans(func: SQLiteDatabase.() -> Unit) { beginTransaction() try { func() setTransactionSuccessful() } finally { endTransaction() }}

db.trans { delete("tableName", "firstName =?", arrayOf("Jake"))}

Page 25: Kotlin

Extension function в infix форме

fun main(args : Array<String>) { val res = 1 add 2 println("$res")}

infix fun Int.add (value : Int) : Int = this + value

• Если extension ф-ия принимает только один аргумент, то вы можете вызвать их в infix форме (убирается "." между типом и функции). Таким образом, вместо 1.add(2), вы можете вызвать его в виде 1 add 2. Это заставляет выглядеть некоторые конструкции более естественно и особенно полезны в строительстве DSL в Котлин.

Page 26: Kotlin

У Kotlin нет примитивных

типов

Page 27: Kotlin

Так что там с Android ?

Page 28: Kotlin

kotterknifepublic class PersonView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { val firstName: TextView by bindView(R.id.first_name) val lastName: TextView by bindView(R.id.last_name)

// Optional binding. val details: TextView? by bindOptionalView(R.id.details)}

https://github.com/JakeWharton/kotterknife

Уже старо !!! Последний update был Aug 19, 2016

Page 29: Kotlin

kotlinx.android// Using R.layout.activity_main from the main source setimport kotlinx.android.synthetic.main.activity_main.*

class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) textView.setText("Hello, world!") // Instead of findView(R.id.textView) as TextView }}

https://kotlinlang.org/docs/tutorials/android-plugin.html

Page 30: Kotlin

Ankoclass MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } } }}

https://github.com/Kotlin/anko

Page 31: Kotlin

Проблемы• Наследование у data class’ов. Обещают в версии 1.1• Lint для Kotlin - мало проверок• Подсветка кода - не такая хорошая как для Java• Incremental compilation - пока не работает стабильно• С непривычки надо не забывать что листы нельзя

изменять (они не мутабильные)• Runtime null checks - если null все таки попался, то

приложение валиться. • Тернарые операторы (x ? y : z) - Выход val max = if (a > b) a

else b

Page 32: Kotlin

Проблемы• При достаточно сложной архитектуре

приложения необходимо будет сделать некоторый рефаторинг

• Не такое большое комюнити, в отличие от Java и Scala (пока что)

• Документация могла быть и лучше• Проблемы с annotation processing (все меньше и

меньше)• Из-за молодости языка нет каких-то

выведенных best practices для решения конкретных задач

Page 33: Kotlin

Что нас ждет в Kotlin v1.1

Page 34: Kotlin

Underscore for unused parameters

data class Person( val name: String, val city: String, val age: Int)

fun printAll(persons: List<Person>) { val children = persons.filter { persons.forEach { (name, _, age) -> println("$name is $age years old")}

Page 35: Kotlin

Restructuring for lambdas

data class Person( val name: String, val city: String, val age: Int)

fun sayHelloToChildren(persons: List<Person>) { val children = persons.filter { persons -> persons.age < 18 }

Page 36: Kotlin

Restructuring for lambdas

data class Person( val name: String, val city: String, val age: Int)

fun sayHelloToChildren(persons: List<Person>) { val children = persons.filter { persons -> persons.age < 18 }

children.forEach { (name, city) -> println("Hello $name from $city") }}

Page 37: Kotlin

Local delegated properties

fun main(args: Array<String>) { val text by lazy { "Hello world!" }

if (Math.random() > 0.5) { println(text) }}

Page 38: Kotlin

Asynchronous computations

Предположим, что нам надо выполнить следующий код:

loadImage().whenComplete { image -> resize(image).whenComplete { resizedImage -> panel.setImage(resizedImage) }}

Page 40: Kotlin

CoroutinesloadImage().whenComplete { panel.setImage(image)}

asyncUI { val image = await(loadImage()) panel.setImage(image)}

Page 41: Kotlin

Q&A

Page 42: Kotlin

Спасибо :)

• Try Kotlin online - http://try.kotlinlang.org/• Documentation -

http://kotlinlang.org/docs/reference/