Added kotlin guide. (WIP) (15.10.26)
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
---
|
||||
title: Пакеты и импорты
|
||||
description: Объявление пакетов, импорты, псевдонимы и автоматически импортируемые пакеты
|
||||
tags:
|
||||
- kotlin
|
||||
- syntax
|
||||
---
|
||||
|
||||
## Пакет
|
||||
Объявляется первой строкой файла:
|
||||
```kotlin
|
||||
package com.example.app
|
||||
|
||||
fun helper() { }
|
||||
class Service
|
||||
```
|
||||
Полное имя функции - `com.example.app.helper`.
|
||||
|
||||
Отличие от Java: **структура каталогов не обязана совпадать с пакетом**, и имя файла не связано с содержимым. Компилятор не возражает. На практике соглашение соблюдают: иначе навигация по проекту ломается.
|
||||
|
||||
Файл без `package` попадает в корневой пакет (default package).
|
||||
|
||||
## Содержимое файла
|
||||
В одном файле может быть сколько угодно объявлений верхнего уровня:
|
||||
```kotlin
|
||||
package com.example
|
||||
|
||||
const val VERSION = "1.0"
|
||||
|
||||
fun parse(text: String): Int = text.toInt()
|
||||
|
||||
class User(val name: String)
|
||||
class Admin(val name: String)
|
||||
|
||||
private fun internalHelper() { } // видна только в этом файле
|
||||
```
|
||||
Никаких `public class` на файл - ограничения «один публичный класс на файл» в Kotlin нет.
|
||||
|
||||
## Импорты
|
||||
```kotlin
|
||||
import com.example.app.Service // конкретный класс
|
||||
import com.example.app.helper // функция верхнего уровня
|
||||
import com.example.app.* // всё из пакета
|
||||
import com.example.app.User.Companion.create // член companion object
|
||||
```
|
||||
Импортировать можно не только типы, но и функции, свойства, enum-константы - всё, что объявлено на верхнем уровне или как статический член.
|
||||
|
||||
```kotlin
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.sqrt
|
||||
|
||||
fun main() {
|
||||
println(sqrt(PI)) // 1.7724538509055159
|
||||
}
|
||||
```
|
||||
|
||||
## Псевдонимы - as
|
||||
Когда имена конфликтуют или слишком длинные:
|
||||
```kotlin
|
||||
import com.example.data.User as DataUser
|
||||
import com.example.api.User as ApiUser
|
||||
|
||||
fun convert(u: DataUser): ApiUser = ApiUser(u.name)
|
||||
```
|
||||
Псевдоним действует только в своём файле. Если нужно имя на весь модуль - это [typealias](../Базовые%20типы%20ООП/Typealias.md).
|
||||
|
||||
## Импортируются автоматически
|
||||
Эти пакеты доступны без `import`:
|
||||
|
||||
| Пакет | Что содержит |
|
||||
|---|---|
|
||||
| `kotlin.*` | `Int`, `String`, `Any`, базовые функции |
|
||||
| `kotlin.annotation.*` | аннотации |
|
||||
| `kotlin.collections.*` | `List`, `Map`, `listOf`, операции |
|
||||
| `kotlin.comparisons.*` | `compareBy`, `maxOf` |
|
||||
| `kotlin.io.*` | `println`, `readln` |
|
||||
| `kotlin.ranges.*` | диапазоны, `step`, `downTo` |
|
||||
| `kotlin.sequences.*` | `Sequence`, `sequenceOf` |
|
||||
| `kotlin.text.*` | операции со строками |
|
||||
| `java.lang.*` | только на JVM |
|
||||
| `kotlin.jvm.*` | только на JVM |
|
||||
|
||||
Поэтому `println`, `listOf`, `Int` работают из коробки. А `kotlin.math.sqrt` - нет, его импортируют явно.
|
||||
|
||||
## Видимость на верхнем уровне
|
||||
```kotlin
|
||||
public fun api() { } // видна везде (public — по умолчанию)
|
||||
internal fun moduleOnly() { } // видна в своём модуле
|
||||
private fun fileOnly() { } // видна только в этом файле
|
||||
```
|
||||
`protected` на верхнем уровне запрещён - нет класса, от которого наследоваться.
|
||||
Подробнее: [Модификаторы видимости](../../ООП/Модификаторы%20видимости.md)
|
||||
|
||||
## Имя класса-обёртки
|
||||
Функции верхнего уровня попадают в класс, названный по файлу: `Utils.kt` → класс `UtilsKt`. Имя можно задать:
|
||||
```kotlin
|
||||
@file:JvmName("Utils")
|
||||
package com.example
|
||||
|
||||
fun helper() { } // из Java: Utils.helper()
|
||||
```
|
||||
Аннотации уровня файла ставятся **до** `package`. Подробнее: [Kotlin из Java](../../Взаимодействие%20с%20Java/Kotlin%20из%20Java.md)
|
||||
|
||||
> [!info] Отличия от Java
|
||||
> | Java | Kotlin |
|
||||
> |---|---|
|
||||
> | каталоги обязаны совпадать с пакетом | не обязаны (но так принято) |
|
||||
> | имя файла = имя публичного класса | имя файла произвольно |
|
||||
> | один публичный класс на файл | сколько угодно объявлений |
|
||||
> | `import static` для статики | обычный `import` для всего |
|
||||
> | псевдонимов нет | `import ... as Name` |
|
||||
> | автоимпорт только `java.lang` | десять пакетов `kotlin.*` |
|
||||
> | `package-private` по умолчанию | `public` по умолчанию |
|
||||
>
|
||||
> Последняя строка важна: в Java класс без модификатора виден только своему пакету, в Kotlin - всем. Для сокрытия внутренностей библиотеки используют `internal`.
|
||||
|
||||
> [!warning] Подводные камни
|
||||
> **Нет аналога package-private.** `internal` ограничивает *модулем* (единицей компиляции Gradle), а не пакетом. Разделить код на пакеты и спрятать их друг от друга внутри одного модуля нельзя - только разносить по модулям.
|
||||
>
|
||||
> **`import *` не затягивает вложенные пакеты.** `import com.example.*` не даёт доступа к `com.example.data.User`.
|
||||
>
|
||||
> **Конфликт импортов - ошибка компиляции, а не предупреждение.** Два `User` из разных пакетов требуют `as` или полного имени.
|
||||
>
|
||||
> **Функции с одинаковым именем в разных файлах одного пакета конфликтуют.** Два `private fun helper()` в разных файлах - нормально, а два `fun helper()` с одной сигнатурой - ошибка: оба попадают в один пакет.
|
||||
>
|
||||
> **`@file:JvmName` не действует, если имя файла совпадает с именем класса в нём.** Коллизия имён вызовет ошибку компиляции.
|
||||
|
||||
Дополнительно: [Структура проекта](../../Инструментарий/Структура%20проекта.md)
|
||||
Далее: [Null-безопасность](../Null-безопасность/Null-безопасность.md)
|
||||
Reference in New Issue
Block a user