В преддверии старта курса "Kotlin Backend Developer" приглашаем будущих студентов и всех желающих посмотреть открытый урок на тему "Пересмотр «12 факторов»: создаём современный микросервис на Kotlin".Также делимся с вами традиционным переводом полезного материала. Когда вы использовали какой-либо API-интерфейс, хотелось ли вам добавить в него новые функции или свойства? Для решения этой задачи вы можете использовать наследование (создать новый класс на базе существующего) или функцию, которая получает в качестве входного параметра экземпляр класса. В языке программирования Java эта задача обычно решается с помощью класса Utils, но он не виден при использовании функции автозавершения кода, что затрудняет поиск и делает использование этого класса менее интуитивно понятным. Оба этих подхода можно использовать для решения нашей задачи, но ни один из них не дает понятный и хорошо читаемый код. К счастью, на помощь приходит Kotlin с функциями-расширениями и свойствами-расширениями. Они позволяют добавлять в класс нужный функционал без необходимости использовать наследование или создавать функцию, принимающую экземпляр класса в качестве параметра. В Android Studio эти расширения видны при использовании функции автозавершения кода, в отличие от соответствующего аналога в языке Java. Расширения можно использовать в сторонних библиотеках, Android SDK или пользовательских классах. Читайте дальше, если хотите узнать, как повысить читаемость вашего кода с помощью расширений! Представим, что у вас есть класс Dog, описывающий собаку, у которой есть имя, порода и возраст. Допустим, некий приют для животных хочет расширить класс Dog, чтобы в нем была функция, которая печатает информацию о собаке, если кто-то захочет забрать ее себе. Для этого мы реализуем функцию-расширение, которая объявляется как обычная функция, но с одной особенностью: перед именем функции добавляется имя расширяемого класса с точкой. В коде функции вы можете использовать служебное слово this для обращения к объекту-получателю, и у вас есть доступ ко всем членам класса-получателя в пределах функции. Вы можете вызвать функцию printDogInformation() так же, как вы вызываете любую другую функцию в классе Dog. Функции-расширения не являются частью расширяемого класса, поэтому при попытке вызвать их из Java мы не найдем их среди методов расширяемого класса. Как мы увидим позже, расширения декомпилируются в статические методы файла, в котором вы их определили, и получают в качестве входного параметра экземпляр расширяемого класса. Вот как бы выглядел вызов функции-расширения printDogInformation() из Java: Расширения можно также использовать для работы с типами, допускающими неопределенное значение (nullable). Вместо того чтобы делать проверку на null перед вызовом функции-расширения, мы можем создать функцию-расширение для nullable-типа и реализовать проверку на null в коде этой функции. Вот так будет выглядеть функция printInformation(), использующая тип, допускающий неопределенное значение. Как видите, не нужно делать проверку на null перед вызовом функции printInformation(). Представим, что нашему приюту для животных также нужно знать, подходит ли собака по возрасту для передачи в новую семью. Для этого мы реализуем свойство-расширение isReadyToAdopt, которое будет показывать, превышает ли возраст собаки 1 год. Вы можете обратиться к этому свойству-расширению так же, как вы обращаетесь к любому другому свойству в классе Dog. Невозможно переопределить существующую функцию-член класса. Если определить функцию-расширение с такой же сигнатурой, что и у существующей функции-члена класса, то всегда будет вызываться функция-член, так как то, какая именно функция вызывается, зависит от объявленного статического типа переменной, а не от типа значения данной переменной во время выполнения кода. Например, нельзя расширить функцию toUppercase(), применяемую к строковому типу (String), но можно расширить функцию convertToUppercase(). Следствие такого поведения можно увидеть, если попытаться расширить библиотечный тип, которым вы не владеете, когда владелец библиотеки добавил в библиотеку метод с той же сигнатурой, что и у вашего расширения. В этом случае будет вызываться библиотечное расширение, а вы получите только информацию о том, что ваша функция-расширение стала неиспользуемым методом. Мы можем декомпилировать функцию printDogInformation() в Android Studio. Для этого нужно выбрать в меню пункт Tools/Kotlin/Show Kotlin Bytecode (Инструменты/Kotlin/Показать байт-код Kotlin) и нажать кнопку Decompile (Декомпиляция). В декомпилированном виде метод printDogInformation() будет выглядеть так: В реальности функции-расширения являются обычными статическими функциями, которым в качестве входного параметра передается экземпляр класса-получателя. Они не имеют никакой другой связи с классами-получателями. Именно поэтому отсутствуют резервные поля — такие функции на самом деле не добавляют члены в класс. В целом расширения являются полезным инструментом, который следует использовать внимательно. Используя их, следуйте указанным ниже рекомендациям, и ваш код станет более понятным и читаемым. Что следует помнить: Расширения преобразуются в статические функции. Функциям-членам класса всегда отдается предпочтение. Возьмите собаку из приюта! Успехов в программировании! Узнать подробнее о курсе "Kotlin Backend Developer".Посмотреть открытый урок на тему "Пересмотр «12 факторов»: создаём современный микросервис на Kotlin". ЗАБРАТЬ СКИДКУ Редактор