ݺߣ

ݺߣShare a Scribd company logo
Kotlin для Android
Зачем нужен Kotlin для
Android?
• Ограничения языка Java и его проблемы
• Нельзя добавить методы для типов,
определенных платформой либо сторонней
библиотекой (ад из “*Util” классов)
• Проблемы с null
• Отсутсвие немодифицируемых коллекций
Зачем нужен Kotlin для
Android?
• Android поддерживает только Java 6
• Нет Java 8 Date API
• Нет Stream API для коллекций
• Нет лямбда выражений, ссылок на методы,
замыканий
• Try-with-resource (только для Android 4.4+)
• Проверка на null повсюду
Зачем нужен Kotlin для
Android?
• Проблемы дизайна Android API
• Сложная иерархия
• NPE повсюду
• Сложное в использование API
Variables
val sample: String = "Sample String"
Variables
val sample: String = "Sample String”

val sample = "Sample String”
val sample: List<String> = ArrayList()
Variables
val sample: String = null
COMPILE ERROR
Variables
val sample: String? = null
sample?.trim()
sample!!.trim()
Lazy Variables
class SampleFragment : Fragment() {
val margin: Int by lazy
{ resources.getDimensionPixelSize(R.dimen.std_margin) }
}
String Templates
val student = Student(1, "Ivan Ivanov", Date())

println("Student '${student.name}' is on ${student.course} course.")
Functions
fun sum(a: Int, b: Int): Int {

return a + b

}
Single-Expression Functions
fun sum(a: Int, b: Int): Int = a + b
Single-Expression Functions
fun sum(a: Int, b: Int) = a + b
Extension Functions
public final class CalendarUtils {



public static boolean isMonday(Calendar calendar) {

return calendar.get(Calendar.DAY_OF_WEEK) ==
Calendar.MONDAY;

}

}
Calendar calendar = Calendar.getInstance();

boolean isMonday = CalendarUtils.isMonday(calendar);
Extension Functions
fun Calendar.isMonday(): Boolean {

return get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY

}
val calendar = Calendar.getInstance()
val isMonday = calendar.isMonday()
Extension Functions
fun Calendar.isMonday() =
get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
val calendar = Calendar.getInstance()
val isMonday = calendar.isMonday()
Extension Functions
fun View.setPaddingTop(padding: Int) {

setPadding(paddingLeft,
padding,
paddingRight,
paddingBottom)

}
Extension Functions
String name = null;

int nameColumnIndex =

cursor.getColumnIndexOrThrow("nameColumn");

if (!cursor.isNull(nameColumnIndex)) {

name = cursor.getString(nameColumnIndex);

}
fun Cursor.getStringOrNull(columnName: String): String? {

val nameColumnIndex = getColumnIndexOrThrow(columnName)

return if (isNull(nameColumnIndex)) null else getString(nameColumnIndex)

}



fun Cursor.getString(columnName: String) = getStringOrNull(columnName)!!
Extension Functions
fun Cursor.getStringOrNull(columnName: String): String? {

val nameColumnIndex = getColumnIndexOrThrow(columnName)

return if (isNull(nameColumnIndex)) null else getString(nameColumnIndex)

}



fun Cursor.getString(columnName: String) = getStringOrNull(columnName)!
val firstName = cursor!!.getString("nameColumn")
Function Expressions
{ it.toString() }
{ x, y -> x + y }
{ x: Int, y: Int -> x + y }
val sum: (Int, Int) -> Int = { x, y -> x + y }
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
High-order Functions
public fun <T> Array<T>.filter(predicate: (T) -> Boolean): Array<T> {

return …

}
val versions = arrayOf("Gingerbread", “Honeycomb",

"Ice Cream Sandwich”,"Jelly Bean", "Lollipop")

val versionsWithBigLength = versions.filter { it.length > 10 }
High-order Functions
fun String.validateWith(predicate: (String) -> Boolean) =
predicate(this)
val validLength: (String) -> Boolean = { it.length > 10 }

"Kirill".validateWith(validLength)
Extension Function Expressions
• Extension Function - Функция, которая
добавляется к типу не модифицируя его.
• Function Expression - Необъявляемая функция,
которую можно использовать в качестве
выражения (например для передачи параметров
в метод)
• High-order function - Функция, которую
используют другую функцию как параметр либо
возвращает функция
Extension Function Expressions
fun SQLiteDatabase.transact(
transaction: SQLiteDatabase.() -> Unit) {

beginTransaction();

try {

transaction()

setTransactionSuccessful()

} finally {

endTransaction()

}

}
Extension Function Expressions
fun SQLiteDatabase.transact(
transaction: SQLiteDatabase.() -> Unit) {

beginTransaction();

try {

transaction()

setTransactionSuccessful()

} finally {

endTransaction()

}

}
val names = arrayOf("Ivan Invanov")

db.transact { delete("students", "name = ?", names) }
Extension Function Expressions
inline fun SQLiteDatabase.transact(
transaction: SQLiteDatabase.() -> Unit) {

beginTransaction();

try {

transaction()

setTransactionSuccessful()

} finally {

endTransaction()

}

}
Extension Function Expressions
val names = arrayOf("Ivan Invanov")

db.transact { delete("students", "name = ?", names) }
+
inline fun
=
db.beginTransaction();

try {

db.transaction()

db.setTransactionSuccessful()

} finally {

db.endTransaction()

}
Default Arguments
fun setViewVisible(visible: Boolean,

animate: Boolean = true) {

//...

}
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;

}

}
Kotlin class
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

}

}
Data class
data class Student(var course: Int,

var name: String,

val birthday: Date)
Singleton
public final class Singleton {



private static Singleton instance;



public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton();

}

}

}

return instance;

}



public void sayHello() {

System.out.println("Hello!");

}



private Singleton() {}

}
Object
object Singleton {

fun sayHello() = println("Hello!")

}
Коллекции
val names = listOf<String>(..) // Список только для чтения

names

.filter { it.startsWith("A") }

.sortedBy { it }

.map { it.toUpperCase() }

.forEach { print(it) }
Что еще
• Перегрузка операторов
• Type smart cast
• Range
• Расширенное API рефлексии
• Делегирование классов
• Делегирование свойств (Lazy, Observable и др.)
• Destructuring declarations
• Named arguments in function
• Tail recursive functions
• Нет проверяемых исключений
Полезные ссылки
• kotlinlang.org

Официальный сайт языка
• try.kotlinlang.org

Онлайн IDE
• github.com/JetBrains/kotlin

Исходны код проекта (лицензия Apache 2.0)

More Related Content

Kotlin для Android

  • 2. Зачем нужен Kotlin для Android? • Ограничения языка Java и его проблемы • Нельзя добавить методы для типов, определенных платформой либо сторонней библиотекой (ад из “*Util” классов) • Проблемы с null • Отсутсвие немодифицируемых коллекций
  • 3. Зачем нужен Kotlin для Android? • Android поддерживает только Java 6 • Нет Java 8 Date API • Нет Stream API для коллекций • Нет лямбда выражений, ссылок на методы, замыканий • Try-with-resource (только для Android 4.4+) • Проверка на null повсюду
  • 4. Зачем нужен Kotlin для Android? • Проблемы дизайна Android API • Сложная иерархия • NPE повсюду • Сложное в использование API
  • 5. Variables val sample: String = "Sample String"
  • 6. Variables val sample: String = "Sample String”
 val sample = "Sample String” val sample: List<String> = ArrayList()
  • 7. Variables val sample: String = null COMPILE ERROR
  • 8. Variables val sample: String? = null sample?.trim() sample!!.trim()
  • 9. Lazy Variables class SampleFragment : Fragment() { val margin: Int by lazy { resources.getDimensionPixelSize(R.dimen.std_margin) } }
  • 10. String Templates val student = Student(1, "Ivan Ivanov", Date())
 println("Student '${student.name}' is on ${student.course} course.")
  • 11. Functions fun sum(a: Int, b: Int): Int {
 return a + b
 }
  • 12. Single-Expression Functions fun sum(a: Int, b: Int): Int = a + b
  • 14. Extension Functions public final class CalendarUtils {
 
 public static boolean isMonday(Calendar calendar) {
 return calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY;
 }
 } Calendar calendar = Calendar.getInstance();
 boolean isMonday = CalendarUtils.isMonday(calendar);
  • 15. Extension Functions fun Calendar.isMonday(): Boolean {
 return get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
 } val calendar = Calendar.getInstance() val isMonday = calendar.isMonday()
  • 16. Extension Functions fun Calendar.isMonday() = get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY val calendar = Calendar.getInstance() val isMonday = calendar.isMonday()
  • 17. Extension Functions fun View.setPaddingTop(padding: Int) {
 setPadding(paddingLeft, padding, paddingRight, paddingBottom)
 }
  • 18. Extension Functions String name = null;
 int nameColumnIndex =
 cursor.getColumnIndexOrThrow("nameColumn");
 if (!cursor.isNull(nameColumnIndex)) {
 name = cursor.getString(nameColumnIndex);
 } fun Cursor.getStringOrNull(columnName: String): String? {
 val nameColumnIndex = getColumnIndexOrThrow(columnName)
 return if (isNull(nameColumnIndex)) null else getString(nameColumnIndex)
 }
 
 fun Cursor.getString(columnName: String) = getStringOrNull(columnName)!!
  • 19. Extension Functions fun Cursor.getStringOrNull(columnName: String): String? {
 val nameColumnIndex = getColumnIndexOrThrow(columnName)
 return if (isNull(nameColumnIndex)) null else getString(nameColumnIndex)
 }
 
 fun Cursor.getString(columnName: String) = getStringOrNull(columnName)! val firstName = cursor!!.getString("nameColumn")
  • 20. Function Expressions { it.toString() } { x, y -> x + y } { x: Int, y: Int -> x + y } val sum: (Int, Int) -> Int = { x, y -> x + y } val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
  • 21. High-order Functions public fun <T> Array<T>.filter(predicate: (T) -> Boolean): Array<T> {
 return …
 } val versions = arrayOf("Gingerbread", “Honeycomb",
 "Ice Cream Sandwich”,"Jelly Bean", "Lollipop")
 val versionsWithBigLength = versions.filter { it.length > 10 }
  • 22. High-order Functions fun String.validateWith(predicate: (String) -> Boolean) = predicate(this) val validLength: (String) -> Boolean = { it.length > 10 }
 "Kirill".validateWith(validLength)
  • 23. Extension Function Expressions • Extension Function - Функция, которая добавляется к типу не модифицируя его. • Function Expression - Необъявляемая функция, которую можно использовать в качестве выражения (например для передачи параметров в метод) • High-order function - Функция, которую используют другую функцию как параметр либо возвращает функция
  • 24. Extension Function Expressions fun SQLiteDatabase.transact( transaction: SQLiteDatabase.() -> Unit) {
 beginTransaction();
 try {
 transaction()
 setTransactionSuccessful()
 } finally {
 endTransaction()
 }
 }
  • 25. Extension Function Expressions fun SQLiteDatabase.transact( transaction: SQLiteDatabase.() -> Unit) {
 beginTransaction();
 try {
 transaction()
 setTransactionSuccessful()
 } finally {
 endTransaction()
 }
 } val names = arrayOf("Ivan Invanov")
 db.transact { delete("students", "name = ?", names) }
  • 26. Extension Function Expressions inline fun SQLiteDatabase.transact( transaction: SQLiteDatabase.() -> Unit) {
 beginTransaction();
 try {
 transaction()
 setTransactionSuccessful()
 } finally {
 endTransaction()
 }
 }
  • 27. Extension Function Expressions val names = arrayOf("Ivan Invanov")
 db.transact { delete("students", "name = ?", names) } + inline fun = db.beginTransaction();
 try {
 db.transaction()
 db.setTransactionSuccessful()
 } finally {
 db.endTransaction()
 }
  • 28. Default Arguments fun setViewVisible(visible: Boolean,
 animate: Boolean = true) {
 //...
 }
  • 29. 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;
 }
 }
  • 30. Kotlin class 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
 }
 }
  • 31. Data class data class Student(var course: Int,
 var name: String,
 val birthday: Date)
  • 32. Singleton public final class Singleton {
 
 private static Singleton instance;
 
 public static Singleton getInstance() {
 if (instance == null) {
 synchronized (Singleton.class) {
 if (instance == null) {
 instance = new Singleton();
 }
 }
 }
 return instance;
 }
 
 public void sayHello() {
 System.out.println("Hello!");
 }
 
 private Singleton() {}
 }
  • 33. Object object Singleton {
 fun sayHello() = println("Hello!")
 }
  • 34. Коллекции val names = listOf<String>(..) // Список только для чтения
 names
 .filter { it.startsWith("A") }
 .sortedBy { it }
 .map { it.toUpperCase() }
 .forEach { print(it) }
  • 35. Что еще • Перегрузка операторов • Type smart cast • Range • Расширенное API рефлексии • Делегирование классов • Делегирование свойств (Lazy, Observable и др.) • Destructuring declarations • Named arguments in function • Tail recursive functions • Нет проверяемых исключений
  • 36. Полезные ссылки • kotlinlang.org
 Официальный сайт языка • try.kotlinlang.org
 Онлайн IDE • github.com/JetBrains/kotlin
 Исходны код проекта (лицензия Apache 2.0)