Kotlin Developer
6.22K subscribers
259 photos
8 videos
354 links
Самый топовый канал по Kotlin

По вопросам сотрудничества и рекламы: @NadikaKir

Мы на бирже: https://telega.in/c/KotlinSenior
Download Telegram
Что делает функция componentN()?

Функция componentN() возвращает значение переменной и позволяет обращаться к свойствам объекта класса по их порядковому номеру. Генерируется автоматически только для data классов.

Также функцию componentN() можно создать самому для класса, который не является data классом.

class Person(val firstName: String, val lastName: String, val age: Int) {
operator fun component1() = firstName
operator fun component2() = lastName
operator fun component3() = age
}

Теперь можно использовать мульти-декларации для класса Person:

val person = Person("John", "Doe", 30)
val (firstName, lastName, age) = person
println("$firstName $lastName is $age years old.")

В данном примере мы определили функции component1(), component2() и component3() как операторы с ключевым словом operator. Они возвращают значения свойств firstName, lastName и age соответственно. После этого мы можем использовать мульти-декларации для разбивки объекта Person на отдельные переменные.
Какие требования должны быть соблюдены для создания data класса?

Класс должен иметь хотя бы одно свойство, объявленное в основном конструкторе.

Все параметры основного конструктора должны быть отмечены val или var (рекомендуется val).

Классы данных не могут быть abstract, open, sealed или inner.
Kotlin вместо bash. Прокачиваем автоматизацию на сервере

Для решения задач автоматизации рутинных процессов для системных администраторов и DevOps чаще всего используются или bash-сценарии или python. Первое решение косвенно используется и в описании Dockerfile, поскольку сценарий исполняемых команд принципиально ничем не отличается от запуска скрипта в какой-либо shell, второй подход чаще ассоциируется с автоматизацией, связанных с взаимодействием с хранилищами данных. Но несправедливо было бы обойти стороной возможность создания исполняемых сценариев на языке Kotlin, которые могут стать полноценной заменой bash-сценариям.

В этой статье мы рассмотрим несколько примеров использования Kotlin Scripting (KTS) для автоматизации в распределенной системе, будем использовать долгоживущие скрипты с ожиданием заданий через RabbitMQ, а также поработаем с файловой системой, внешними сервисами, а также попробуем использовать KTS для сборки Docker-контейнеров
.

Читать статью
Можно ли наследоваться от data класса?

От data класса нельзя наследоваться т.к. он является final классом, но он может наследоваться от других классов.
Почему классы в Kotlin по умолчанию final?

Классы в Kotlin по умолчанию являются final для того, чтобы избежать случайного наследования и переопределения методов. Это сделано для повышения безопасности кода и уменьшения сложности программы, так как ограничение наследования помогает избежать ошибок, связанных с неожиданным изменением поведения унаследованных методов.

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

По умолчанию, классы в Kotlin объявляются как final, то есть их нельзя наследовать. Если мы всё же попытаемся наследоваться от такого класса, то получим ошибку: “This type is final, so it cannot be inherited from”.

Чтобы класс можно было наследовать, его нужно объявить с модификатором open.

open class Fraction {
...
}

Не только классы, но и функции в Kotlin по умолчанию имеют статус final. Поэтому те функции, которые находятся в родительском классе и которые вы хотите переопределить в дочерних классах, также должны быть отмечены open.

open class Fraction {

open fun toAttack() {
...
}

}

Свойства класса также по умолчанию являются final. Для возможности переопределения таких свойств в дочерних классах, не забудьте и их отметить ключевым словом open.

open class Fraction {

open val name: String = "default"

open fun toAttack() {
...
}

}

При этом, если в открытом классе будут присутствовать функции и свойства, которые не отмечены словом open, то переопределяться они не будут. Но дочерний класс сможет к ним обращаться.

open class Fraction {

open val name: String = "default"

fun toAttack() {
...
}

}

class Horde : Fraction() {
override val name = "Horde"
}

class SomeClass() {
val horde = Horde()
horde.toAttack()
}
Как можно получить тип класса?

1. Получение типа класса через функцию ::class

Функция ::class возвращает объект KClass, который содержит информацию о типе класса во время выполнения.

class Person(val name: String, val age: Int)

fun main() {
val person = Person("John", 30)
println(person::class) // выводит "class Person"
}

2. Получение типа класса через функцию javaClass

Функция javaClass возвращает объект Class, который содержит информацию о типе класса во время выполнения.

class Person(val name: String, val age: Int)

fun main() {
val person = Person("John", 30)
println(person.javaClass) // выводит "class Person"
}

3. Получение типа класса через функцию ::class.java

Вызов функции ::
class.java на объекте типа KClass возвращает объект Class, который содержит информацию о типе класса во время выполнения.

class Person(val name: String, val age: Int)

fun main() {
val person = Person("John", 30)
println(person::class.java) // выводит "class Person"
}
Осознанная оптимизация Compose

Compose — относительно молодая технология написания декларативного UI. Множество разработчиков даже не предполагают, что пишут неоптимальный код в такой критически важной части, и впоследствии это приводит к неожиданной низкой производительности и проседании метрик.

Наша команда Ozon Seller также столкнулась с этой проблемой. Мы решили собрать воедино все советы и наработки по написанию оптимизированного Compose-кода. Активное применение этих советов при оптимизации существующих экранов и написании новых существенно улучшило наши метрики: длительность лага по отношению к длительности скролла (hitch rate; чем меньше, тем лучше) экранов со списками упала в среднем с 15-19 % до 5-7 % (на 90-м перцентиле). Все эти советы и наработки мы описали в этой статье. Она будет полезна и начинающим, и опытным разработчикам, в ней подробно описаны оптимизации и механизмы Compose, а также рассказано про слабо задокументированных особенности и исправления ошибок, которые есть в других статьях. Давайте же начнём.

Читать статью
Что такое sealed класс (изолированный)?

Sealed class (изолированный класс) — это класс, который является абстрактным и используется в Kotlin для ограничения классов, которые могут наследоваться от него.

Основная идея заключается в том, что sealed class позволяет определить ограниченный и известный заранее набор подклассов, которые могут быть использованы.

Конструктор изолированного класса всегда приватен, и это нельзя изменить.

У sealed класса могут быть наследники, но все они должны находиться в одном пакете с изолированным классом. Изолированный класс "открыт" для наследования по умолчанию, указывать слово open не требуется.

Наследники sealed класса могут быть классами любого типа: data class, объектом, обычным классом, другим sealed классом. Классы, которые расширяют наследников sealed класса могут находиться где угодно.

Изолированные классы абстрактны и могут содержать в себе абстрактные компоненты.

Изолированные классы нельзя инициализировать.

При использовании when, все подклассы, которые не были проверены в конструкции, будут подсвечены IDE.

Не объявляется с ключевым словом inner.

Пример sealed класса:

sealed class Shape {
class Circle(val radius: Double) : Shape()
class Rectangle(val width: Double, val height: Double) : Shape()
class Triangle(val base: Double, val height: Double) : Shape()
}

fun calculateArea(shape: Shape): Double {
return when (shape) {
is Shape.Circle -> Math.PI * shape.radius * shape.radius
is Shape.Rectangle -> shape.width * shape.height
is Shape.Triangle -> 0.5 * shape.base * shape.height
}
}

fun main() {
val circle = Shape.Circle(5.0)
val rectangle = Shape.Rectangle(2.0, 3.0)
val triangle = Shape.Triangle(4.0, 5.0)

println(calculateArea(circle)) // Output: 78.53981633974483
println(calculateArea(rectangle)) // Output: 6.0
println(calculateArea(triangle)) // Output: 10.0
}

В этом примере мы определили sealed class Shape, который содержит три класса: Circle, Rectangle и Triangle. Эти классы наследуются от Shape. Это означает, что мы можем создавать объекты этих классов и использовать их, как объекты типа Shape.

В функции calculateArea мы используем выражение when, чтобы определить тип фигуры и вернуть ее площадь. Таким образом, если мы передадим Shape.Circle в calculateArea, то будет вычислена площадь круга.

В функции main мы создали объекты Circle, Rectangle и Triangle и передали их в calculateArea, чтобы вычислить их площади.
Какая разница между sealed class и enum?

Sealed class и Enum это два разных концепта в Kotlin, хотя их часто используют для ограничения набора возможных значений. Основная разница между ними:

• enum представляет собой конечный список значений, которые объявляются заранее в момент компиляции, и не могут быть расширены или изменены во время выполнения программы

• sealed class позволяет определять ограниченный набор значений, но эти значения могут быть расширены в будущем

В общем, enum class используется для представления конечного списка опций или состояний, тогда как sealed class используется для определения ограниченного набора значений, которые могут быть произвольными объектами.
Что такое inner (внутренние) и nested (вложенные) классы?

В Kotlin можно объявить один класс внутри другого. Это может быть полезно в тех случаях, когда вам нужно организовать код и логически связать классы между собой. Подобные классы разделяются на внутренние (inner) и вложенные (nested).

1. Внутренние классы (inner classes) имеют доступ к членам внешнего класса, даже если они объявлены как private. Внутренний класс является частью внешнего класса и имеет доступ к его свойствам и методам. В Kotlin внутренний класс объявляется с помощью ключевого слова inner. Например:

class Outer {
private val outerProperty = "Outer Property"

inner class Inner {
fun innerMethod() {
println("Accessing outer property: $outerProperty")
}
}
}

В этом примере Inner является внутренним классом, а Outer является внешним классом. Inner имеет доступ к членам Outer, в том числе к приватным свойствам и методам, таким как outerProperty.

2. Вложенные классы (nested classes) не имеют доступа к членам внешнего класса по умолчанию. Они имеют свои собственные члены, которые могут быть использованы только внутри класса. Например:

class Outer {
private val outerProperty = "Outer Property"

class Nested {
fun nestedMethod() {
println("Accessing nested property")
}
}
}

Здесь Nested является вложенным классом. Он не имеет доступа к свойству outerProperty, но может использовать свои собственные члены, такие как nestedMethod.

3. Ключевое отличие: внутренний (inner) класс — это вложенный (nested) класс, который может обращаться к компонентам внешнего класса.
Строим мосты: подключение зависимостей с Cocoapods в Kotlin Multiplatform Mobile

При создании КММ проекта Android Studio предоставляет разработчику выбор между использованием Regular Framework и Cocoapods Dependency Manager для добавления iOS-специфических библиотек, который может быть крайне неочевидным на первый взгляд, ведь использование Regular Framework кажется затруднительным и не пользуется популярностью в отличие от удобного Cocoapods. В данной статье мы рассмотрим, как интегрировать Cocoapods в разработку, создав небольшое Android приложение.

Читать статью
Какая польза от typealias? Во что он компилируется?

Typealias — это механизм создания синонимов (псевдонимов) для существующих типов. То есть, можно создать новое имя для уже существующего типа данных.

Псевдонимы типов полезны, когда вы хотите сократить длинные имена типов, содержащих обобщения. К примеру, можно упрощать названия типов коллекций:

typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K, MutableList<File>>

Польза от использования typealias заключается в том, что он повышает читабельность кода, делает его более выразительным и удобным для работы. Кроме того, он может упростить процесс переписывания кода в случае изменения типов в будущем.

К примеру, если в проекте используется много Map<String, String> и вместо этого вы хотите использовать более описательное название, например Properties, вы можете определить новый тип для Map<String, String> с помощью следующего кода:

typealias Properties = Map<String, String>

Теперь вместо использования Map<String, String> можно использовать Properties для обозначения одного и того же типа данных. Таким образом, код становится более читаемым и понятным.

Во что компилируется
typealias?

Typealias не создает новый тип данных, а только создает псевдоним для существующего типа. При компиляции кода, все typealias заменяются на соответствующий тип, поэтому typealias не приводит к увеличению размера кода.

Например, typealias IntPredicate = (Int) -> Boolean при компиляции будет заменено на (Int) -> Boolean, то есть функцию, принимающую значение типа Int и возвращающую значение типа Boolean.

Можно ли использовать
typealias для функциональных типов?

Да, можно использовать typealias для функциональных типов в Kotlin. Например, вы можете создать псевдоним для типа функции, которая принимает два параметра типа Int и возвращает значение типа String, следующим образом:

typealias IntToString = (Int, Int) -> String

Это позволит вам использовать созданный псевдоним вместо полного объявления типа, то есть вместо:

fun processValues(f: (Int, Int) -> String) {
// ...
}

можно использовать:

fun processValues(f: IntToString) {
// ...
}

Как и в случае с другими typealias, компилятор Kotlin просто заменяет псевдоним на соответствующий тип при компиляции кода.
Что такое функции высшего порядка (higher-order functions), лямбда-выражения (lambda-expressions), анонимные функции (anonymous functions), указатели на методы (method references, bound callable references)?

Функции высшего порядка - это функции, которые принимают функцию в качестве аргумента и/или возвращает функцию в качестве результата

Лямбда выражения - не объявленная функция, которая немедленно используется в качестве выражения

Анонимные функции - альтернативный синтаксис лямбда выражения с иными правилами для выражения return(можно использовать для создания блока кода с несколькими точками выхода )

Указатели на методы - упрощенный синтаксис создания значения функции, вызывающего ровно один метод или обращающегося к свойству.
{p:Person --> p.age} ==Person::age
Какой толк от inline-функций, как компилируется сама функция и места её использования?

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

Когда функция объявляется с модификатором inline, её тело становится встраиваемым, т.е. оно подставляется вместо обычного вызова функции.

Если отметить функцию модификатором inline, компилятор не будет генерировать вызов функции в месте её использования, а просто вставит код её реализации.
Alfa Backend Stories Meetup #2 🔥

26 июля встречаемся на митапе для бэкенд-разработчиков: эксперты из Альфы и Авито обсудят межсерверное взаимодействие и архитектурные паттерны, которые могут упростить жизнь разработчику.

🔺 Александр Карташов, Senior Java Developer, расскажет про технологии межсервисного взаимодействия на примере проектов Альфа-Банка.

🔺 Василий Рыбин, Java Developer, познакомит с архитектурным паттерном API Gateway.

🔺 Павел Агалецкий, Lead Engineer в Авито, рассмотрит механики валидации контрактов внутренних API и протокол межсервисного взаимодействия в Авито.

🔺 Екатерина Попкова, Java/Kotlin Developer, расскажет, что такое Сага и как его можно реализовать на Camunda Platform 8.

✔️ Зарегистрироваться на митап и узнать больше о программе
Можно ли сделать extension к интерфейсу? Тайпалиасу? Функциональному типу?

Интерфейс - да
Псевдонимы типов - да
функциональный тип - нет(там есть Литералы функций с объектом-приёмником)
companion/object - да
Как адаптировать Android-приложение под Huawei

Всем привет! Меня зовут Миша Вассер, я Head of Android в AGIMA. Мы занимаемся разработкой Digital-продуктов для больших и маленьких компаний, в том числе пилим мобильные приложения.

Не так давно — по сравнению со всей историей Android — Huawei выкатил собственную операционную систему и сказал: «Ребята, вот вам новая система, кайфуйте». Многие отнеслись к новой ОС скептически. Остальным пришлось адаптировать под нее свои Android-приложения.

Мы оказались во второй группе. К нам время от времени обращаются с просьбой помочь с адаптацией под Huawei. И мы неплохо в этом вопросе прокачались. Поэтому сейчас расскажу, что надо сделать, чтобы стало хорошо. А покажу всё это на примере крупного ретейлера, с которым мы работаем.

Читать статью
Во что компилируется typealias?

Typealias не создает новый тип данных, а только создает псевдоним для существующего типа. При компиляции кода, все typealias заменяются на соответствующий тип, поэтому typealias не приводит к увеличению размера кода.

Например, typealias IntPredicate = (Int) -> Boolean при компиляции будет заменено на (Int) -> Boolean, то есть функцию, принимающую значение типа Int и возвращающую значение типа Boolean.

Можно ли использовать typealias для функциональных типов?

Да, можно использовать typealias для функциональных типов в Kotlin. Например, вы можете создать псевдоним для типа функции, которая принимает два параметра типа Int и возвращает значение типа String, следующим образом:

typealias IntToString = (Int, Int) -> String

Это позволит вам использовать созданный псевдоним вместо полного объявления типа, то есть вместо:

fun processValues(f: (Int, Int) -> String) {
// ...
}

можно использовать:

fun processValues(f: IntToString) {
// ...
}

Как и в случае с другими typealias, компилятор Kotlin просто заменяет псевдоним на соответствующий тип при компиляции кода.
Какие коллекции есть в Kotlin?

Коллекция
— это объект, содержащий в себе набор значений одного или различных типов, а также позволяющий к этим значениям обращаться и извлекать. Другими словами — это контейнер, в который вы можете помещать то, что вам нужно, а затем каким-либо образом с ним взаимодействовать. В Kotlin есть три типа коллекций:

List (список). Упорядоченная коллекция, в которой к элементам можно обращаться по их индексам. Идентичные элементы (дубликаты) могут встречаться в списке более одного раза. Примером списка является предложение: это группа слов, их порядок важен, и они могут повторяться.

Set (множество/набор). Неупорядоченная коллекция без повторяющихся значений. Примером множества является алфавит.

Map (словарь/ассоциативный список). Набор из пар "ключ-значение". Ключи уникальны и каждый из них соответствует ровно одному значению. В коллекции могут присутствовать повторяющиеся значения, но не повторяющиеся ключи. Пример — ID сотрудников и их должностей. Map не является наследником интерфейса Collection.

Два типа интерфейсов, на основе которых создаются коллекции:

1. Неизменяемый (read-only) — дают доступ только для чтения (Set, List, Map, Collection).

2. Изменяемый (mutable) — расширяет предыдущий интерфейс и дополнительно даёт доступ к операциям добавления, удаления и обновления элементов коллекции (
MutableSet, MutableList, MutableMap, MutableCollection).
Давно в IT и хотите сменить профиль? Стремитесь попробовать что-то новое? Испытайте себя в роли Java-разработчика на практике! Популярность языка Java растёт, востребованность разработчиков — тоже. А возрастных ограничений для специалистов нет.

Бесплатный онлайн интенсив пройдёт с 31 июля по 2 августа в 19:00 по московскому времени.

Регистрация: 👉https://epic.st/sd-oR-

Сразу после регистрации пришлём гайд по профессии Java-разработчика 😉

За 3 вечера вы узнаете, в чем различия Python и Java, какие навыки нужны для трудоустройства Java-разработчику, и попробуете написать Telegram-бота на Java. В него будет «зашит» тест по Java от реального работодателя, но вы сможете модифицировать его и реализовать собственную логику.

🔝Знаниями поделится Даниил Пилипенко — основатель и директор центра подбора IT-специалистов SymbioWay.

🎁 Тем, кто будет онлайн, подарим сертификаты на скидку 10 000 рублей для обучения на образовательной платформе Skillbox. А всем, кто дойдёт до конца интенсива, — электронную книгу издательства МИФ.

Реклама. ЧОУ ДПО «Образовательные технологии «Скилбокс (Коробка навыков)», ИНН: 9704088880