Подібна проблема виникла б, якби ми говорили про кількість різних пристроїв, на яких зараз працює Android; якби не Java. Завдяки потужності Java і тому, що сьогодні її використовують на мільярдах пристроїв, вона здатна працювати на будь-якому пристрої незалежно від його апаратного та програмного забезпечення, якщо на ньому є інтерпретатор псевдокомпільованого коду, згенерованого компілятором Java.
Java — розв’язання всіх проблем?
На жаль, ніщо не може бути далі від істини. Хоча Java розв’язує проблему взаємодії між пристроями, вона відкриває цілу низку нових головних болів, яких нам хотілося б позбутися. Ось деякі з них:
Немає вбудованої підтримки необов’язкових параметрів
Хоча для незмінних колекцій така підтримка є. Попри наявність класу Optional, його використання означає генерування великої кількості шаблонного коду, якого можна було б уникнути, якби підтримка опцій була вбудована в саму мову, а не додавалася як її розширення.
Немає нативної підтримки функціонального програмування: у Java є Stream Api (повторюся, він підтримується лише в Android, починаючи з API 24), але його інтеграція в мову виглядає факультативною: він погано вписується в об’єкти, пов’язані з примітивними типами (IntStream, DoubleStream...), і для всіх інших об’єктів є клас Stream .
Підтримка анонімних функцій (Lambdas). Хоча в Java 8 реалізовано підтримку функцій Lambda, вони не є об’єктами першого класу; це означає, що, хоча ми можемо використовувати лямбда-вирази для реалізації анонімних інтерфейсів з одним методом, Java не підтримує передавання функцій як аргументів методу.
Крім того, відсутність виведення типів робить запис Lambdas досить незручним, особливо коли намагаєшся імітувати такі функції, як композиція функцій або карування; у мові немає їхньої підтримки.
Обнулюваність типів: хоча це можна було б включити до розділу про необов’язкові параметри, масштаб цієї проблеми заслуговує на окрему згадку. Скільки Java-програмістів не заповнювали свій код перевірками if (foo! = Null), намагаючись боротися зі страшним NullPointerException? (Насправді його творець вибачився за те, що називає «помилкою на мільярд доларів»). І скільки з цих перевірок — це радше латки, щоб не дати нашому застосунку впасти?
Ручне прив’язування представлень: хоча ця проблема специфічна для Android як платформи, а не для Java як мови, варто також згадати про кількість шаблонного коду, потрібного, щоб отримати посилання на представлення Android. Хоча завдяки прив’язці даних нам вдалося позбутися ненависного findViewById (int id), нам усе одно потрібно зберігати посилання на цю прив’язку.
Більш загальна, але не менш важлива проблема — Java — дуже багатослівна мова, вона вимагає писати багато коду для будь-якої операції, а також генерувати багато файлів (по одному на клас). Перша проблема може призвести до того, що код стане дорожчим в обслуговуванні та більш схильним до помилок. Друга — це проблема розмноження класів.
Багато з цих проблем, хоча їх і розв’язано в Java 8 і 9, недоступні в Android SDK нижче API 24, через що ними практично неможливо скористатися.
Чому мова Kotlin дає з усім цим раду?
Саме з усіх цих причин сьогодні Java вважають мовою, яка, принаймні в розробці Android, не розвивається з тією швидкістю, з якою розвивається індустрія.
З часом потреба в мові зі справжньою нативною підтримкою всього переліченого вище стає дедалі нагальнішою, водночас важливо зберегти головну особливість Android, про яку йшлося на початку цієї статті: можливість написати й скомпілювати один застосунок так, щоб він працював на будь-якому пристрої та будь-якій його версії.
У цьому напрямку досліджували багато варіантів, зокрема використання Swift або Scala, хоча жоден із них не був багатообіцяльним.
Усе змінилося з появою мови Kotlin.
Щоб почати це демонструвати, перелічімо всі недоліки, з якими ми стикаємося в Java, і те, як мова Kotlin із ними справляється:
Опції.
Вони вбудовані в Kotlin: усе, що потрібно зробити, — оголосити тип змінної зі знаком питання в кінці? — і вона стане необов’язковим типом. Мова Kotlin також дає змогу безпечно розгортати ці опції через listener?.onSuccess(), не перевіряючи, чи має опція значення, а ще надає оператор Елвіса.
Функціональне програмування: у Kotlin є вбудована підтримка роботи з колекціями та наборами даних, такими як Streams. Ми можемо безпосередньо викликати .flatMap {} для колекції, а також .filter {}, .map {} та багато інших методів. Виведення типів робить використання лямбда-виразів особливо зручним.
Лямбди і функції вищого порядку. Попередній пункт доповнює той факт, що в мові Kotlin функції є об’єктами першого класу. Ми можемо визначати функції, які отримують інші функції як параметри. Прикладом цього є визначення самої функції map:
Хоча на перший погляд цей код може видатися трохи хаотичним, нас цікавить ось ця частина.
Це означає, що функція map має параметр з іменем transform, який сам є функцією: вона приймає вхідний параметр типу T і повертає об’єкт типу R.
Завдяки вбудованій підтримці лямбда-виразів у мові Kotlin ми можемо використовувати функцію map так:
Цей фрагмент коду поверне колекцію елементів типу, який повертає aTransformation.
Обнулюваність типів: у мові Kotlin, оскільки вона має вбудовану підтримку необов’язкових параметрів, у нашому коді має бути якомога менше значень, що можуть бути null. Але навіть якщо такі значення є, Kotlin пропонує нам інструменти, які допомагають працювати з ними простіше, ніж у Java. Наприклад, ми маємо оператор безпечного виклику (?), щоб уникнути винятку NullPointerException під час доступу до необов’язкових параметрів, або оператор безпечного приведення типу, який захистить нас, якщо ми захочемо виконати приведення.
Крім того, компілятор Kotlin змушує контролювати типи, які можуть мати значення null, і навіть додає перевірки під час виконання на випадок сумісності з кодом Java.
Прив’язування представлень: це специфічна проблема Android, тому Jetbrains пропонує нам Kotlin Android Extensions — офіційну бібліотеку підтримки, яка спрощує цю проблему (та деякі інші) за допомогою плагіна gradle.
Усе сказане вище, а також велика кількість інших можливостей, які не ввійшли до цієї статті або не були для нас справді важливими, показують, що мова Kotlin видається найперспективнішим вибором на найближчі кілька років у світі розробки мобільних пристроїв.









