Имея за плечами опыт с Java, я понял, что синтаксис Kotlin похож на Java, но в то же время может сильно отличаться. Kotlin — очень мощный язык, в котором много синтаксического сахара, что может немного напрягать.
В этой статье мы рассмотрим необходимый минимум, который поможет начать работать с Kotlin. Давайте сразу к делу.
1. Переменные
Чтобы объявить переменную, используйте var.
var username: String = "some user name"
Чтобы объявить константу, используйте val. val в Kotlin — это как final в Java.
val API_DELAY_CONSTANT: Int = 100
Чтобы инициализировать переменную как null, используйте оператор “?”. Если оператор “?” не указан, то компилятор не позволит присвоить переменной значение null.
var myString: String? = null
Используйте companion object для определения статической переменной.
class Animal {
companion object {
const val DEFAULT_NUM_OF_EYES = 2
}
}
animal.numOfEyes = Animal.DEFAULT_NUM_OF_EYES
Используйте lateInit для отложенной инициализации переменной.
lateinit var user: User // Initialized later in code lateinit var items: List<String> // Initialized later in code
2. Функции
Простая функция в Kotlin выглядит следующим образом:
fun getNumber(): Int { return 1 }
Здесь функция getNumber() имеет область видимости public, не имеет параметров и возвращает Int.
Попробуем создать private функцию с несколькими параметрами.
private fun getStringLength(str1: String, str2: String): Int { return str1.length + str2.length }
Функция getStringLength() имеет область видимости private и два параметра, возвращает Int.
Как насчёт статической функции?
class MyStringUtil { companion object { fun getOddLengthString(str: String): String? { if (str.length % 2 == 0) return null return str } } } var str: String = MyStringUtil.getOddLengthString("hey")
getOddLengthString() — статическая функция, которая принимает параметр и возвращает строку. Тип String указан с символом “?”. Это означает, что функция может возвращать значение NULL.
3. Циклы for, while, when
В цикле for, в Kotlin, используется ключевое слово “in” для доступа к элементам коллекции.
var items: List<String> = ArrayList<String>() for (item in items) { // do something with item }
Можно также получить доступ к индексам элементов в цикле for.
for (index in items.indices) { // access items using index // items.get(index) }
Цикл while в Kotlin такой же, как и в Java. Тут ничего нового 🙂
var i: Int = 0 // Some while loop do { // do something i++ } while (i < 5) // Another while loop while (i < 10) { // do something i++ }
А вот оператор switch в Java был создан проще. Kotlin использует ключ слово when для переключения между условиями, и это гораздо более мощный и краткий способ.
// A cool example of when statement fun describe(obj: Any): String? { var res: String? = null when (obj) { 1 -> { res = "One" } // if obj == 1 "Hello" -> res ="Greeting" // if obj == "Hello" is Long -> "Long" // if obj is of type Long !is String -> "Not string" // if obj is not of type String else -> { // execute this block of code } } return res }
4. Null Safety (Null безопасность)
В Java, чтобы избежать исключения NullPointerException, мы можем использовать блок “if”. Например:
if (person != null && person.department != null) { person.department.head = managersPool.getManager() }
Но в Kotlin мы можем пропустить блок “if” и переписать наш код следующим образом:
// If either `person` or `person.department` is null, the function is not called: person?.department?.head = managersPool.getManager()
“?.”известен как оператор безопасного вызова, и приведённый выше пример показывает, что его можно использовать в цепочках. Это помогает нам писать чистый, простой код и в то же время избегать NPE.
В случае, если вы хотите обработать сценарий, где объект равен null, вы можете использовать “?:”. Этот оператор, называют — Elvis operator.
var name = person?.name ?: throw InvalidDataException("Person cannot be null.")
5. Классы (конструкторы, методы, наследования)
Ключевое слово “open” указывает, что класс может быть унаследован. Класс, который не является “open”, такой же, как класс final в Java. Простой пример класса в Kotlin выглядит так:
open class Animal { // This class is open and // can be inherited } class Dog : Animal() { // Notice the paranthesis // Class dog is final and // can't be inherited } // Compiler throws error class Labrador : Dog { }
Ниже приведён более сложный пример класса и наследования в Kotlin:
open class Animal { // Parent class var name: String? = null // Nullable variable var legs: Int = 0 // Non-nullable variable lateinit var map: HashMap<Integer, String> // Variable inited later in the code constructor(legs: Int) { this.legs = legs } constructor(legs: Int, name: String) { this.legs = legs this.name = name } // open keyword allows the function to be overridden open fun speak() : String? { return null } } class Dog : Animal { // Child class constructor(legs: Int) : super(legs) { // Optional code block } // Just a super call, without additional code block constructor(legs: Int, name: String) : super(legs, name) // Function over-ridding override fun speak(): String? { return "Bark! Bark!" } }
Обратите внимание, что в наших классах нет методов getter и setter. Вместо этого мы обращаемся к свойствам объекта следующим образом:
var dog: Dog = Dog(0) // Setters dog.numOfLegs = 4 dog.name = "Labrador" // Getter println(dog.name)
6. Singleton (синглтоны)
Синглтоны в Kotlin реализуются с помощью ключевого слова “object”. Имея опыт с Java, использование “object” вместо “class”, кажется немного странным. Подробнее об этом можно прочитать в официальных документах Kotlin:
object Singleton { var name: String = "singleton object" fun printName() { println(name) } } // later in the code Singleton.name Singleton.printName()
7. Интерфейсы
Базовый интерфейс в Kotlin выглядит следующим образом:
interface Named { fun bar() } interface Person : Named { // Person inherits Named fun foo() } class Employee() : Person { override fun bar() { // do something } override fun foo() { // do something } }
Наследование интерфейса довольно просто. Но передача интерфейса функции немного отличается. Посмотрите на этот пример:
// A function that accepts and interface as a parameter private fun setEventListener(listener: EventListener) { // do something } // Passing an interface to the function setEventListener(object : EventListener{ override fun call() { // do something } })
8. Type Casts (приведение типов)
Чтобы проверить, является ли объект экземпляром определённого класса, мы используем операторы “is” и “!is”.
if (obj is String) { print(obj.length) } if (obj !is String) { print("Not a String") }
Чтобы предотвратить выбрасывание исключений, можно использовать оператор безопасного приведения “as?”, который возвращает null при сбое. Это называется safe typecast в Kotlin.
val x: String? = y as? String
В этом случае при сбое приведения типов, возвращается значение null, что предотвращает выбрасывание исключений.
9. Обработка исключений
Выбрасывание и обработка исключений практически такие же, как и в Java.
throw Exception("Hi There!") try { // some code } catch (e: SomeException) { // handler } finally { // optional finally block }
Перевод статьи: Mayur Rokade Learn Kotlin for Android in One Day