Todo kotlin что это

Todo kotlin что это

Если статья вам понравилась, то можете поддержать проект.

Коты забавные, поэтому ввели ключевое слово fun (есть спорное мнение, что на самом деле это сокращение от «function» для обозначения функций, которые являются аналогами методов в Java).

Объявление функции начинается с ключевого слова fun, затем идёт имя функции, в круглых скобках указываются параметры. Тип возвращаемого значения указывается после списка параметров и отделяется от него двоеточием. Функция всегда возвращает значение. Если вы сами не указали возвращаемое значение, то функция вернёт Unit, который схож с void, но является объектом.

Стандартный вывод «Hello Kitty» для Kotlin-программы (Desktop, не Android):

Данная функция ничего не возвращает. Напишем другую функцию, возвращающую результат.

Обратите внимание, что if является выражением в Kotlin, а не Java-оператором и соответствует тернарному оператору в Java:

Простую функцию, в которой блок состоит из одной строки кода, можно переписать в одну строчку.

Можно даже убрать возвращаемый тип. Гулять так гулять.

Такой способ подходит только для функций, в которых Kotlin способен самостоятельно разобраться, чего хотел разработчик, т.е. с телом-выражением в правой части. В правой части мы вычисляем какой-то результат, который обычно передавали в return. Теперь мы можем отказаться от return и фигурных скобок, и сразу присваивать результат функции.

В других случаях (тело-блок) вы обязаны указывать возвращаемый тип и использовать инструкцию return.

Функции верхнего уровня можно импортировать для сокращения кода.

Доступен вариант со звёздочкой.

Можно даже изменить имя и создать псевдоним при помощи ключевого слова as. Этот вариант может оказаться полезным, если имеются несколько одинаковых названий функций из разных пакетов и хочется избежать путаницы и конфликтов.

Именованные параметры

Мы привыкли, что при вызове метода следует соблюдать очерёдность параметров. С именованными параметрами такая необходимость отпала. Создадим новую функцию из двух параметров.

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

Несмотря на то, что мы поменяли местами параметры, итоговый результат всё равно будет работать правильно. Такой подход может пригодиться, когда вы не помните порядок и вам лень смотреть документацию.

Данный приём не сработает при работе с методами, написанными на Java. Поддержка именованных аргументов есть в Java 8, но Kotlin поддерживает совместимость с Java 6, поэтому приходится смириться. Возможно, в будущем, эта проблема решится автоматически, когда откажутся от поддержки старых версий.

Параметры по умолчанию

Добавим в класс активности новую функцию для вывода всплывающего сообщения (в примере используется функция-расширение).

Второй параметр использует значение по умолчанию и мы можем его не указывать при вызове. Вызываем функцию.

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

Вызываем функцию с двумя параметрами, надеясь, что третий подставится самостоятельно. Но Kotlin не может решить, какой параметр пропущен.

В этом случае на помощь приходят именованные параметры.

Третий параметр теперь нам известен, опущенный параметр относится ко второму, оставшийся относится к первому.

У класса Thread имеется восемь конструкторов! Вы можете создавать гораздо удобные решения с параметрами по умолчанию.

Unit. Если функция ничего не возвращает

Стоит немного рассказать о функциях, которые не возвращают никаких значений. В Java мы используем ключевое слово void для подобных случаев. В Kotlin был придуман новый тип Unit для подобных ситуаций. Получается, что функция всегда что-то возвращает, в нашем случае Unit, который мы никак не используем.

Но Kotlin достаточно умен и понимает, что мы не хотим ничего возвращать. Поэтому мы можем сократить код.

Можно сократить код, убрав фигурные скобки, так как у функции только одно выражение.

Вызываем функцию с любым количеством аргументов.

Если функция имеет и другие параметры, то они должны быть раньше vararg. Можно обойти это правило, если использовать именованные параметры, но лучше избегать таких ситуаций.

По сути vararg работает с массивом, но простое добавление массива Kotlin не пропустит. Следует использовать специальный оператор *.

Вложенные (локальные) функции

Внутри одной функции можно создать ещё одну локальную функцию.

Вложенная функция имеет доступ к переменным своей родительской функции.

Функции верхнего уровня

Функцию можно объявить в начале файла, не обязательно размещать его в теле класса. Это удобно, когда вам нужны методы, которые не относятся к конкретному классу или вы не хотите перезагружать имеющийся класс лишним кодом. Часто для этих целей программисты создавали отдельные классы со словом Util.

Размещая код метода за пределами класса, вы избегаете лишней вложенности. Они по-прежнему являются членами пакета, прописанного в файле и могут импортироваться при использовании в других пакетах.

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

Kotlin незаметно для вас создаст класс CatsKt по имени файла и все функции скомпилирует в статические методы. Если будете вызывать функцию в Java-коде, то это будет выглядеть следующим образом.

Если имя класса вас не устраивает, то добавьте аннотацию @JvmName перед именем пакета.

Тогда вызов в Java-коде будет другим.

Функция TODO()

В стандартную библиотеку Kotlin входит функция TODO() (надо сделать). Её описание выглядит следующим образом.

Функция TODO() возбуждает исключение, т.е. вызов функции гарантированно завершится ошибкой — она возвращает тип Nothing. Считайте функцию временной заглушкой. Разработчик знает, что некоторая функция должна вернуть строку или другой объект, но пока отсутствуют другие функции, необходимые для ее реализации. Создадим для примера две функции.

Обратите внимание, что возвращаемое значение для shouldReturnAString() — это String, но на самом деле функция ничего не возвращает. Аналогично у shouldReturnACat().

Возвращаемый тип Nothing у TODO() показывает компилятору, что функция гарантированно вызовет ошибку, поэтому проверять возвращаемое значение после TODO() не имеет смысла, так как shouldReturnAString() и shouldReturnACat() ничего не вернут. Компилятор не будет ругаться, а разработчик может продолжать разработку, отложив на потом реализацию функции-заглушки.

Функцию можно вызвать без аргументов. Код, который будет следовать за функцией, будет недостижим.

Имена функций в обратных кавычках

Можно объявить или вызвать функцию с именем, содержащим нестандартные символы. Для этого достаточно заключить имя в обратные кавычки `. Например, объявим функцию:

Данная возможность нужна, чтобы поддерживать совместимость с Java в тех моментах, когда встречаются зарезервированные ключевые слова. Использование обратных кавычек позволяют избежать несовместимости в случаях, если это необходимо. На практике такое почти не встречается.

На данный момент под Android такой способ не работает, студия будет ругаться.

Источник

ToDo List App with Kotlin and Firebase

Firebase is a real-time database which provides immense features to manage a mobile app. Actually, not even a mobile app, complex web apps and enterprise applications can make use of Firebase with virtually unlimited performance.

In this lesson we will cover many of Firebase features and its usage, using a simple ToDo app build with Kotlin and powered by Firebase Database API. Let’s get started.

Firebase

Firebase offers many features with its strong API and unlimited performance. We will mention some of these here:

New Project in Android

We will be creating a new project in Android to demonstrate a simple app as a ToDo List app build with Kotlin and using Firebase Database with a complete set of CRUD(Create, Read, Update Delete) operations.

Adding Firebase support

Next, we add Firebase support in our application. This can be done easily from inside the Android Studio itself. Click Tools > Firebase to open the Assistant window.

Todo kotlin что это. todo list kotlin firebase 1. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 1. картинка Todo kotlin что это. картинка todo list kotlin firebase 1

Once that is done, the Firebase assistant will appear presenting many Firebase services, we need to select the `Realtime Database` feature:

Todo kotlin что это. todo list kotlin firebase 2. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 2. картинка Todo kotlin что это. картинка todo list kotlin firebase 2

Once you click ‘Setup Firebase Realtime Database’, following dialog will appear to confirm setting up the project:

Todo kotlin что это. todo list kotlin firebase 3. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 3. картинка Todo kotlin что это. картинка todo list kotlin firebase 3

Next, Android Studio will offer to add relevant code snippets to our app like Gradle dependency:

With other changes, it is clearly shown in the dialog Android Studio presented us:

Todo kotlin что это. todo list kotlin firebase 4. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 4. картинка Todo kotlin что это. картинка todo list kotlin firebase 4Adding Real Time Firebase Database

Setting Firebase project access rules

This lessons is not meant for authentication purposes. So, the ToDo items we add in our app will be accessible to all the users using the same app as we’re accessing the same database irrespective of the user identity. So, to make our database public, we will add the following script in our Firebase project access rules:

Todo kotlin что это. todo list kotlin firebase 5. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 5. картинка Todo kotlin что это. картинка todo list kotlin firebase 5Setting up Firebase Database Access Rules

In the Data tab above, you will find a URL like:

Though this URL is not important as our app will access the Firebase over the network and Firebase will identify which database to access via the app’s package name itself and the google-services.json file added automatically by Firebase during its setup.

Add Database collection name

We will add our Database collection name in a new File in Kotlin whose content will be as follows:

Our collection name will be todo_item. We will see where will this appear as soon as we save first item in Firebase.

As of now, our Database on Firebase looks like:

Todo kotlin что это. todo list kotlin firebase 6. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 6. картинка Todo kotlin что это. картинка todo list kotlin firebase 6

Adding a To Do Item model

Here, we will design a model object which will be used to hold data for our ToDo list item data. We will intentionally keep this very simple for demonstration purposes.

Let us understand what we’ve done in this simple model:

Designing the app

Now that the complete configuration is done and we’ve finalised the data model, we can start working on the simple but intuitive design.

We need following functionalities in our app:

To start, we need following elements:

Our initial UI will look like this:

Todo kotlin что это. todo list kotlin firebase 7. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 7. картинка Todo kotlin что это. картинка todo list kotlin firebase 7

To make this simple UI, we kept these properties in XML in res > layout > activity_main.xml file as:

When this FloatingActionButton is clicked, we need to show a dialog with an EditText where user can enter new item and save it with Database.

Showing a Dialog on FloatingActionButton click

To do this, we must do following steps:

Let’s make changes to our Activity now. We first define a FloatingActionButton in onCreate(…) method which points to the FloatingActionButton in our XML above.

Then we set a click listener on it.

In addNewItemDialog function, we will show a dialog. As of now, our complete onCreate(…) method looks like:

Let’s add the method to show the dialog next:

Once we add the above code, alert dialog will appear once we hit the FloatingActionButton:

Todo kotlin что это. todo list kotlin firebase 8. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 8. картинка Todo kotlin что это. картинка todo list kotlin firebase 8

Creating entry in Firebase

This is where our real journey starts. In this section, we will start inserting data into the Firebase. We have already shown the current state of the database. Now, let’s modify the code of positive button listener of the dialog as:

Let us see what we did above:

We’ve used mDatabase in above code. What is it?

mDatabase is the Firebase database reference. Let’s create it as a Global variable in our Activity.

And initialise it in our onCreate(…) method:

As simple as that. Now, run the app once again, enter some value and hit ‘Submit’. The item will appear in the Firebase Database as:

Todo kotlin что это. todo list kotlin firebase 9. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 9. картинка Todo kotlin что это. картинка todo list kotlin firebase 9

Reading Firebase data in a List

What is the use of the data until and unless we’re able to read the data. In the previous section, we designed a simple UI with a ListView. Now, we will enhance it with custom UI for its row.

This is a simple UI which will create following row design:

Todo kotlin что это. todo list kotlin firebase 10. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 10. картинка Todo kotlin что это. картинка todo list kotlin firebase 10

Clearly, this row is enough to update item state as done using the CheckBox and to delete the row via the ImageButton.

To populate the ListView, we must create a new Adapter which will complete this responsibility.

In above adapter, we:

Now, we must use this Adapter in our Activity. Also, we also have to fetch data from Firebase.

Fetching data from Firebase

Getting data from Firebase is actually easy. Just do this in onCreate(…) method:

We will add item listener next. We just add a listener for current database which will fetch and alert the function when the data has been fetched.

We first define some global variables, as:

We will initialise each of them in our onCreate(…) method. Once all this is done, our method will look like:

Finally, our listener looks like:

What each line does is explained in above code itself. Now, we’re ready to show the data in our ListView. Once we run our app now, we can see the data as:

Todo kotlin что это. todo list kotlin firebase 11. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 11. картинка Todo kotlin что это. картинка todo list kotlin firebase 11

We are left with two operations. Updating the item as done or undone by checking that CheckBox. Second by clicking on that cross image to delete this data.

Update and Delete ToDo items

Now, to perform these operations. We must know when each of our row is clicked. Also, we need to get the ObjectID of the row that was clicked. This can be obtained from the Adapter.

Let’s start by creating an Kotlin Interface file as:

Clearly, we want to provide two operations.

Next, we will make our activity implement this interface by doing:

As we’ve implemented an interface, we must implement its methods as well:

We need to call these methods via our adapter. In our getView(…) method, we can do as:

This can only be done if we define rowListener in our Adapter class:

Now, once we click on checkbox as done, our database will change as:

Todo kotlin что это. todo list kotlin firebase 12. Todo kotlin что это фото. Todo kotlin что это-todo list kotlin firebase 12. картинка Todo kotlin что это. картинка todo list kotlin firebase 12

Value has been changed.

Persisting Firebase data offline

Firebase is excellent in caching data. Once you run the app and get your data, Firebase will cache to so that it can be used offline as well. Once your app is back online, it will update the data.

The caching behaviour is off by default. Let’s modify this behavior.

We will create an Application class now:

That’s it! Just a single line of code and caching is enabled. Of course, you need to add this Application class in your Manifest file:

Our full fledged To Do Item application is ready.

Conclusion

In this lesson, we looked at CRUD(Create, Read, Update, Delete) operations of Firebase and how fast it is to sync with web server. We completed CRUD operations in our elegant app and enjoyed it as well.

Firebase also has strong caching techniques through which it promises strong user experience by presenting them data even when there is no network. We can do a lot more with Firebase like saving images etc. Let’s save it for another time.

To learn more about Mobile Apps Development with Kotlin check out the below books and video courses, they will certainly help you speed up your learning progress.

Источник

Разбираемся в типах Kotlin — Unit, Nothing, Any (и null)

Todo kotlin что это. thumb 80e95fce07e5f138e45c0194a3da992c. Todo kotlin что это фото. Todo kotlin что это-thumb 80e95fce07e5f138e45c0194a3da992c. картинка Todo kotlin что это. картинка thumb 80e95fce07e5f138e45c0194a3da992c

Todo kotlin что это. thumb 80e95fce07e5f138e45c0194a3da992c. Todo kotlin что это фото. Todo kotlin что это-thumb 80e95fce07e5f138e45c0194a3da992c. картинка Todo kotlin что это. картинка thumb 80e95fce07e5f138e45c0194a3da992c

Todo kotlin что это. retina cb9951fab2f1f690c9d25cc0dea54a8b. Todo kotlin что это фото. Todo kotlin что это-retina cb9951fab2f1f690c9d25cc0dea54a8b. картинка Todo kotlin что это. картинка retina cb9951fab2f1f690c9d25cc0dea54a8b

В Kotlin есть интересный набор базовых типов, который в какой-то мере соотносится с Java. Это Unit, Nothing, Any. Давайте посмотрим, что эти классы представляют собой, чем отличаются (несмотря на похожие названия), и сравним их с аналогами в Java. Ещё поговорим немного про null в Kotlin, потому что эти темы связаны.

Unit эквивалентен void в Java. В этом выражении возвращаемый тип можно не указывать, если функция ничего не возвращает. По умолчанию там будет Unit:

В Kotlin есть два способа объявить функцию: в теле метода (в фигурных скобках) или как выражение (через знак равенства). Можно переписать нашу функцию так, а заодно указать возвращаемое значение:

В стандартной библиотеке Kotlin Unit определён как объект, наследуемый от Any и содержащий единственный метод, переопределяющий toString():

Обратите внимание на ключевое слово object. Это значит, что Unit является синглтоном. Unit ничего не возвращает, а метод toString всегда будет возвращать “kotlin.Unit”. При компиляции в java-код Unit всегда будет превращаться в void.

Интересно, что в Java есть свой класс Void, который довольно слабо, но всё же соотносится с void и не может быть инстантирован. Это исключительно утилитарный класс, который нужен для рефлексии и дженериков в Java.

Nothing

С Nothing всë гораздо интереснее. Nothing — класс, который является наследником любого класса в Kotlin, даже класса с модификатором final. При этом Nothing нельзя создать — у него приватный конструктор. В коде он объявлен так:

Несмотря на всë это, класс Nothing довольно полезен. Так как невозможно передать или вернуть тип Nothing, он описывает результат «функции, которая никогда ничего не вернёт». Примером может быть функция, которая выбрасывает exception или в которой запущен бесконечный цикл: в любом из этих случаев она никогда не вернёт значения. В приложениях — независимо от того, какой тип данных возвращает функция, — она может никогда не вернуть данные, потому что произошла ошибка или вычисления затянулись на неопределённый срок. В этом случае имеет смысл использовать Nothing.

Посмотрим, где это используется в Kotlin. Вот пример: функция TODO(), которая часто служит заглушкой в автоматически генерируемых методах.

Вы можете наблюдать такую картину при автогенерации кода:

Код прекрасно скомпилируется, потому что Nothing наследуется от Something. Но приложение сразу же упадёт с NotImplementedError, если вы вызовете метод doSomething.

Интересно, что в Java нельзя написать что-то подобное: код просто не скомпилируется, потому что Void не наследуется от String:

Ещё один пример может касаться выполнения, например, запроса данных из БД или удалённого сервера. Если произошла ошибка, можно возвращать null вместо данных. И это абсолютно нормально, данных-то нет:

А если хочется немного больше информации, чем просто null? Например, узнать тип ошибки. Вот тут Nothing приходит на помощь:

Вот как это может выглядеть в коде:

Класс Any находится на вершине иерархии — все классы в Kotlin являются наследниками Any. Any — это аналог Object в Java, но с меньшим количеством методов:

В java.lang.Object одиннадцать методов, и пять из них касаются многопоточности. Несмотря на меньшее количество методов, при компиляции в Java-код у любого класса появятся недостающие — тут можно быть спокойными.

В Java можно вызывать методы объекта всегда, и только в процессе работы программы вы узнаете, что объект у вас null. Тогда приложение падает с ошибкой NPE (NullPointerException). Это самая частая ошибка в Java вообще.

Создавая Kotlin, разработчики старались сделать его максимально безопасным. Напишем такой код:

Что получим в результате? Ошибку компиляции. Чтобы в переменной можно было хранить null, надо объявить её соответствующим образом:

Если попытаться присвоить переменной, не поддерживающей null, значение переменной с поддержкой nullable-типов, компилятор не даст скомпилировать такой код:

Также мы не сможем вызвать методы объекта, хранящегося в такой переменной:

Чтобы присвоить значение nullable-переменной, не поддерживающей null, надо сначала проверить, не содержит ли nullable-переменная null:

После этого в области видимости проверки переменная nullable будет рассматриваться компилятором как тип, не поддерживающий null. Можно безопасно обращаться к хранимому в переменной объекту.

Защита от NullPointerException реализована на уровне компилятора. Это касается не только переменных, но и выражений, и вызовов функций. Компилятор не даст передать в функцию значение переменной, которая поддерживает nullable-типы, если в определении функции заявлены только nonNull-параметры. И не даст присвоить переменной, не поддерживающей null, значение, полученное из выражения, которое может возвращать null.

Посмотрим ещё пример из Java:

При выполнении этого кода программа упадёт с ошибкой. И узнаем мы об этом только во время исполнения. Конечно, это упрощённый вариант кода, где ошибку видно сразу. Но в реальной программе обнаружить такие баги бывает непросто. Что предлагает Kotlin:

В Kotlin с его nullable-типами такой код попросту не скомпилируется. У класса Person в конструкторе заявлены параметры типов, не поддерживающих null в качестве значения. Поэтому компилятор может это отследить и не даст собрать такой код. Только если вы явно и с определённой целью укажете, что параметры могут быть null, — код скомпилируется и приложение запустится. Но тогда вся ответственность за NPE лежит на вас:

В Java нет поддержки null-безопасности на уровне языка, поэтому там приходится использовать аннотации. Это не только добавляет лишние строки кода, но и не гарантирует безопасность — код прекрасно собирается и принимает null даже там, где он не должен быть. Аннотация только подсвечивает проблемные места. В Kotlin же такой код просто не соберётся.

Оператор безопасного вызова

Первый такой инструмент — оператор безопасного вызова. Выглядит как вопросительный знак с последующей точкой:

Производит проверку на null перед вызовом метода. Если значение переменной равно null, то вместо вызова исключения это выражение просто вернёт null. То есть если name == null, то nameLength будет == null или же nameLength будет == 4. Очень удобная и быстрая проверка, которая часто используется в коде (в своём приложении мы тоже будем прибегать к помощи этого оператора).

Оператор «Элвис»

Принцип работы следующий: если выражение слева вернёт не null, то мы получим длину имени; если же null, то вернётся значение выражения справа от оператора. Таким образом легко реализуется проверка на null и возврат значения по умолчанию. Исходя из примера выше, если name == null, то nameLength будет == 1 или же nameLength будет == 4.

На этом пока всё, остаёмся на связи! Это первая статья из цикла «Ликбез». Следующие материалы будут про коллекции, extensions, множественное наследование, Sealed Classes и многое другое — следите за блогом!

Todo kotlin что это. retina cb9951fab2f1f690c9d25cc0dea54a8b. Todo kotlin что это фото. Todo kotlin что это-retina cb9951fab2f1f690c9d25cc0dea54a8b. картинка Todo kotlin что это. картинка retina cb9951fab2f1f690c9d25cc0dea54a8b

В Kotlin есть интересный набор базовых типов, который в какой-то мере соотносится с Java. Это Unit, Nothing, Any. Давайте посмотрим, что эти классы представляют собой, чем отличаются (несмотря на похожие названия), и сравним их с аналогами в Java. Ещё поговорим немного про null в Kotlin, потому что эти темы связаны.

Unit эквивалентен void в Java. В этом выражении возвращаемый тип можно не указывать, если функция ничего не возвращает. По умолчанию там будет Unit:

В Kotlin есть два способа объявить функцию: в теле метода (в фигурных скобках) или как выражение (через знак равенства). Можно переписать нашу функцию так, а заодно указать возвращаемое значение:

В стандартной библиотеке Kotlin Unit определён как объект, наследуемый от Any и содержащий единственный метод, переопределяющий toString():

Обратите внимание на ключевое слово object. Это значит, что Unit является синглтоном. Unit ничего не возвращает, а метод toString всегда будет возвращать “kotlin.Unit”. При компиляции в java-код Unit всегда будет превращаться в void.

Интересно, что в Java есть свой класс Void, который довольно слабо, но всё же соотносится с void и не может быть инстантирован. Это исключительно утилитарный класс, который нужен для рефлексии и дженериков в Java.

Nothing

С Nothing всë гораздо интереснее. Nothing — класс, который является наследником любого класса в Kotlin, даже класса с модификатором final. При этом Nothing нельзя создать — у него приватный конструктор. В коде он объявлен так:

Несмотря на всë это, класс Nothing довольно полезен. Так как невозможно передать или вернуть тип Nothing, он описывает результат «функции, которая никогда ничего не вернёт». Примером может быть функция, которая выбрасывает exception или в которой запущен бесконечный цикл: в любом из этих случаев она никогда не вернёт значения. В приложениях — независимо от того, какой тип данных возвращает функция, — она может никогда не вернуть данные, потому что произошла ошибка или вычисления затянулись на неопределённый срок. В этом случае имеет смысл использовать Nothing.

Посмотрим, где это используется в Kotlin. Вот пример: функция TODO(), которая часто служит заглушкой в автоматически генерируемых методах.

Вы можете наблюдать такую картину при автогенерации кода:

Код прекрасно скомпилируется, потому что Nothing наследуется от Something. Но приложение сразу же упадёт с NotImplementedError, если вы вызовете метод doSomething.

Интересно, что в Java нельзя написать что-то подобное: код просто не скомпилируется, потому что Void не наследуется от String:

Ещё один пример может касаться выполнения, например, запроса данных из БД или удалённого сервера. Если произошла ошибка, можно возвращать null вместо данных. И это абсолютно нормально, данных-то нет:

А если хочется немного больше информации, чем просто null? Например, узнать тип ошибки. Вот тут Nothing приходит на помощь:

Вот как это может выглядеть в коде:

Класс Any находится на вершине иерархии — все классы в Kotlin являются наследниками Any. Any — это аналог Object в Java, но с меньшим количеством методов:

В java.lang.Object одиннадцать методов, и пять из них касаются многопоточности. Несмотря на меньшее количество методов, при компиляции в Java-код у любого класса появятся недостающие — тут можно быть спокойными.

В Java можно вызывать методы объекта всегда, и только в процессе работы программы вы узнаете, что объект у вас null. Тогда приложение падает с ошибкой NPE (NullPointerException). Это самая частая ошибка в Java вообще.

Создавая Kotlin, разработчики старались сделать его максимально безопасным. Напишем такой код:

Что получим в результате? Ошибку компиляции. Чтобы в переменной можно было хранить null, надо объявить её соответствующим образом:

Если попытаться присвоить переменной, не поддерживающей null, значение переменной с поддержкой nullable-типов, компилятор не даст скомпилировать такой код:

Также мы не сможем вызвать методы объекта, хранящегося в такой переменной:

Чтобы присвоить значение nullable-переменной, не поддерживающей null, надо сначала проверить, не содержит ли nullable-переменная null:

После этого в области видимости проверки переменная nullable будет рассматриваться компилятором как тип, не поддерживающий null. Можно безопасно обращаться к хранимому в переменной объекту.

Защита от NullPointerException реализована на уровне компилятора. Это касается не только переменных, но и выражений, и вызовов функций. Компилятор не даст передать в функцию значение переменной, которая поддерживает nullable-типы, если в определении функции заявлены только nonNull-параметры. И не даст присвоить переменной, не поддерживающей null, значение, полученное из выражения, которое может возвращать null.

Посмотрим ещё пример из Java:

При выполнении этого кода программа упадёт с ошибкой. И узнаем мы об этом только во время исполнения. Конечно, это упрощённый вариант кода, где ошибку видно сразу. Но в реальной программе обнаружить такие баги бывает непросто. Что предлагает Kotlin:

В Kotlin с его nullable-типами такой код попросту не скомпилируется. У класса Person в конструкторе заявлены параметры типов, не поддерживающих null в качестве значения. Поэтому компилятор может это отследить и не даст собрать такой код. Только если вы явно и с определённой целью укажете, что параметры могут быть null, — код скомпилируется и приложение запустится. Но тогда вся ответственность за NPE лежит на вас:

В Java нет поддержки null-безопасности на уровне языка, поэтому там приходится использовать аннотации. Это не только добавляет лишние строки кода, но и не гарантирует безопасность — код прекрасно собирается и принимает null даже там, где он не должен быть. Аннотация только подсвечивает проблемные места. В Kotlin же такой код просто не соберётся.

Оператор безопасного вызова

Первый такой инструмент — оператор безопасного вызова. Выглядит как вопросительный знак с последующей точкой:

Производит проверку на null перед вызовом метода. Если значение переменной равно null, то вместо вызова исключения это выражение просто вернёт null. То есть если name == null, то nameLength будет == null или же nameLength будет == 4. Очень удобная и быстрая проверка, которая часто используется в коде (в своём приложении мы тоже будем прибегать к помощи этого оператора).

Оператор «Элвис»

Принцип работы следующий: если выражение слева вернёт не null, то мы получим длину имени; если же null, то вернётся значение выражения справа от оператора. Таким образом легко реализуется проверка на null и возврат значения по умолчанию. Исходя из примера выше, если name == null, то nameLength будет == 1 или же nameLength будет == 4.

На этом пока всё, остаёмся на связи! Это первая статья из цикла «Ликбез». Следующие материалы будут про коллекции, extensions, множественное наследование, Sealed Classes и многое другое — следите за блогом!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *