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

Оглавление

Массивы

Списки

Наборы и карты

Список массивов

Лямбда-выражения

Модификаторы доступа

Внутренние и вложенные классы

Обработка исключений

Массивы

как мы видели это раньше вкратце. это тип данных, содержащий набор данных, поэтому давайте создадим массив

fun main() {
    val nums : IntArray = intArrayOf (1,2,3,4,5,6,7,8,9,10)
}

как мы знаем, это kotlin, мы можем сделать это объявление более простым

fun main() {
    val nums  = intArrayOf (1,2,3,4,5,6,7,8,9,10)
}

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

fun main() {
    val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
}

все то же самое, но мы сделали его более простым

Примечание: тип данных массива — это ссылка на первый элемент массива, ссылка — это расположение переменной внутри памяти, поэтому массивы содержат ссылку на первый элемент своих элементов, давайте посмотрим

fun main() {
    val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
    println(nums)
}//output 
//[Ljava.lang.Integer;@8efb846

что это за выход? это то, о чем мы говорили, он напечатал местоположение первого элемента массива, а не самого. value , помните, когда мы говорили о классах в разделе oop, давайте создадим класс и попробуем напечатать его также, чтобы объяснить ссылку

fun main() {
    val ref :ExplainRefrence = ExplainRefrence("Mohab")
    print(ref)
}

class ExplainRefrence (name : String ){
    val name : String
    init {
        this.name=name
    }
}//output ExplainRefrence@7adf9f5f

он не печатал удобочитаемую вещь, прямо эта ссылка «Где этот объект хранится внутри памяти», это то же самое для массива, если мы хотим напечатать массив, мы этого не делаем.

Поскольку это kotlin, внутри этого массива есть метод, называемый contentToString(), который будет печатать содержимое массива.

fun main() {
    val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
    println(nums.contentToString())

}// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

давайте теперь попробуем распечатать элемент за элементом, используя цикл for, который мы рассматривали ранее.

fun main() {
    val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
for (i in nums ){
    println(i)
}
}//1
//2
//3
//4
//5
//6
//7
//8
//9
//10

Примечание: в массивах первый элемент начинается с 0 , поэтому индекс (1) равен 0, а не (1) компьютер начинает считать с 0 , посмотрите на пример ниже

fun main() {
val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
println(nums[0])
}//output 
//1

мы также можем переназначить эти значения, как показано ниже

fun main() {
    val nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)
    println(nums[5])
    nums [5]= 100
    println(nums[5])
}

всегда обязательно передайте существующий индекс внутри [] не делайте, как показано ниже

fun main() {
    val  nums  = arrayOf (1,2,3,4,5,6,7,8,9,10)

    println(nums[12])
}

Исключение в потоке «main» java.lang.ArrayIndexOutOfBoundsException: индекс 12 выходит за границы для длины 10
в MainKt.main(Main.kt:4)
в MainKt.main(Main.kt )

что случилось, массив имеет только 10 элементов, так как мы можем напечатать элемент, существующий в 12-м элементе, который никогда не существует

давайте посмотрим на пример хранения внутри массивов

fun main() {
    val  nums  = arrayOf (1,2,3,4,5,6,7,8,9,false )
val strgns = arrayOf("Mohab","Messi","Neymar")
val bools = arrayOf(false , true )
var mixed = arrayOf(false , 123.0,11123,"Mohab" )
}

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

fun main() {
    val type1 =MyOwntype("Mohab")
    val type2 =MyOwntype(false )
    val type3 =MyOwntype(122 )
val myArray = arrayOf(type1,type2,type3)

    print(myArray[0].toString())
}

data class MyOwntype (val anyType : Any )

//output MyOwntype(anyType=Mohab)

Списки

также хранит один или несколько типов

fun main() {
    val players = listOf("Messi","Neymar","Ronaldo")
    print(players[0])
}//Messi

также мы можем перебрать его

fun main() {
    val players = listOf("Messi","Neymar","Ronaldo")
    for (player in players){
        println(player)
    }
}//
//Messi
//Neymar
//Ronaldo
fun main() {
    val players = listOf("Messi","Neymar","Ronaldo")
players.forEach( ){
    println(it)
}
}//Messi
//Neymar
//Ronaldo

it → относится к элементу внутри списка, подобномуplayers[n]

fun main() {
    val players = listOf("Messi","Neymar","Ronaldo")
println(players.size)
}//3

теперь этот список неизменяем, и мы не можем добавлять в него элементы

но мы можем преобразовать его в неизменяемый

fun main() {
    val players = listOf("Messi","Neymar","Ronaldo")
 val mutablePlayers =    players.toMutableList()

    mutablePlayers.add("Mohab")
    println(mutablePlayers[3])
}//Mohab

мы можем создать список mutbale, как показано ниже

fun main() {
    val players = mutableListOf<String >("Messi","Neymar","Ronaldo")
    players.add("hakimi")

}

‹String› это дженерики, которые сообщают компилятору, эй, это изменяемый список только String, который является необязательным

fun main() {
    val players = mutableListOf("Messi","Neymar","Ronaldo")
    players.add("hakimi")
}

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

fun main() {
    val players = mutableListOf<Any>("Messi","Neymar","Ronaldo")
    players.add(111.213)
}

мы сделали его списком «Любой», чтобы мы могли хранить любой тип, давайте посмотрим, как сделать список пустым или удалить элемент

fun main() {
    val players = mutableListOf<Any>("Messi","Neymar","Ronaldo")
println(players)
    players.remove("Messi")
    println(players)
players.removeAt(1)
println(players)
players.removeAll(players)
 println(players)
}// output 
//[Messi, Neymar, Ronaldo]
//[Neymar, Ronaldo]
//[Neymar]
//[]

Наборы

тип коллекции, которая удаляет повторяющиеся элементы, не отсортированная коллекция, также имеет изменяемые и неизменяемые классы, mutableSetOf() setOf()

fun main() {
val players = setOf ("Messi","Messi","Messi","Ronaldo")
    println(players.size)
}//output 
//2

да, мы сохранили 4 элемента, но на самом деле их только 2, которые уникальны, и именно так работает набор, он удаляет дубликаты, «Как математика в школе»

попробуем разобраться

fun main() {
val players = setOf ("Ronaldo","Messi","Messi","Messi","Abou Trika")
    println(players.sorted())
}//[Abou Trika, Messi, Ronaldo]

он отсортировал его по алфавиту, давайте сделаем его изменяемым

fun main() {
val players = setOf ("Ronaldo","Messi","Messi","Messi","Abou Trika")
    println(players.sorted())
    val mutablePlayers = mutableSetOf("Ronaldo","Messi","Messi","Messi","Abou Trika")
    mutablePlayers.add("Ronaldinho")
    mutablePlayers.add("Neymar")
    println(mutablePlayers.sorted())

}//output 
//[Abou Trika, Messi, Ronaldo]
//[Abou Trika, Messi, Neymar, Ronaldinho, Ronaldo]

Карты

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

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

fun main() {
val playersMap = mapOf(11 to "Neymar",10 to "Messi",22 to "Abou trika")

}

вот как мы объявляем карту, мы говорим, что neymar (значение) имеет 11 (ключ), но что произойдет, если мы сохраним два значения с одним и тем же ключом, как показано ниже?

fun main() {
val playersMap = mapOf(11 to "Neymar",10 to "Messi",22 to "Abou trika",11 to "Ronaldo")
    print(playersMap[11])
}// Ronaldo

первое значение с повторяющимся ключом будет перезаписано для сохранения нового

посмотрите ниже, как получить доступ к значению внутри карты, используя его ключ

print(playersMap[11]) 

мы можем получить доступ ко всем ключам или значениям, как показано ниже,

fun main() {
val playersMap = mapOf(11 to "Neymar",10 to "Messi",22 to "Abou trika",11 to "Ronaldo")

    for (key in playersMap.keys){
        println(key)
    }
}// output 
//11
//10
//22
fun main() {
val playersMap = mapOf(11 to "Neymar",10 to "Messi",22 to "Abou trika",11 to "Ronaldo")

    for (player in playersMap.values){
        println(player)
    }
}//
//Ronaldo
//Messi
//Abou trika

также мы можем получить доступ к обоим

fun main() {
val playersMap = mapOf(11 to "Neymar",10 to "Messi",22 to "Abou trika",11 to "Ronaldo")

    for (key in playersMap.keys){
        println("in your map $key holds ${playersMap[key]}")
    }
}//output 
//in your map 11 holds Ronaldo
//in your map 10 holds Messi
//in your map 22 holds Abou trika

ключи могут быть любым типом данных, а не только целыми,

fun main() {
val playersMap = mapOf("11" to "Neymar","10" to "Messi","22" to "Abou trika","11" to "Ronaldo")

    for (key in playersMap.keys){
        println("in your map $key holds ${playersMap[key]}")
    }
}//
//in your map 11 holds Ronaldo
//in your map 10 holds Messi
//in your map 22 holds Abou trika

смотрите, мы также изменили его на строки, давайте сделаем его изменяемым

fun main() {

    val mutablePLayersMap= mutableMapOf("11" to "Neymar","10" to "Messi","22" to "Abou trika","11" to "Ronaldo")
    mutablePLayersMap.putIfAbsent("1","Cassialls")
    print(mutablePLayersMap)
}// 
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Cassialls}

putIfAbsent() это поместит inisde карты, если переданный ему ключ не существует

fun main() {

    val mutablePLayersMap= mutableMapOf("11" to "Neymar","10" to "Messi","22" to "Abou trika","11" to "Ronaldo")
    mutablePLayersMap.putIfAbsent("1","Cassialls")
    println(mutablePLayersMap)
    mutablePLayersMap.putIfAbsent("1","Neuer")
    println(mutablePLayersMap)
}//
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Cassialls}
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Cassialls}

посмотрите, как он вставлен в первый раз, так как ключ не существует, но после того, как он не вставлен, давайте посмотрим на put()

fun main() {

    val mutablePLayersMap= mutableMapOf("11" to "Neymar","10" to "Messi","22" to "Abou trika","11" to "Ronaldo")
    mutablePLayersMap.putIfAbsent("1","Cassialls")
    println(mutablePLayersMap)
    mutablePLayersMap.putIfAbsent("1","Neuer")
    println(mutablePLayersMap)
    mutablePLayersMap.put("1","Neuer")
    println(mutablePLayersMap)

}//output 
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Cassialls}
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Cassialls}
//{11=Ronaldo, 10=Messi, 22=Abou trika, 1=Neuer}

put добавит его на карту, даже если он существует, перезаписав то же значение с тем же ключом

ArrayList

динамически распределяется, означает, что его размер может быть увеличен или уменьшен, мы также можем читать и писать на нем, также он сортируется при добавлении элементов, также может иметь дублированные элементы

val myList = ArrayList<Any>() // empty arrayList 
val myList = ArrayList<Any>(100) // array with limted size of 100 elements only 
myList.add()//add an element to arrayList
myList.clear()// clears the arrayList
myList.get(0) // get the eleemnt of [n] index
myList.remove("mohab")// removes eleemtns from arrayList

Лямбда-выражения

позволяет нам написать короткий код, функция, у которой нет имени (не анонимус), эта функция не объявлена, она передается как выражение, тело функции пишется после -> (эта стрелка) называется лямбда

давайте посмотрим нормальную функцию, которая возвращает значение типа int

fun main() {
println(add(1,2))
    
}
fun add (x : Int , y : Int ):Int {
    return  x+y ;
}
//output 
//3

лямбда-функция

fun main() {
println(lambdaAdd(1,2))
    
}
val lambdaAdd: (Int , Int )->Int = {a:Int , b : Int ->a+b}

мы можем перепечатать это, как показано ниже, также

fun main() {
println(shorterLambdaAdd(1,2))
}
val shorterLambdaAdd = {x : Int , y : Int ->x+y }

еще короче,

fun main() {
println(shorterLambdaAdd)
}
val shorterLambdaAdd = {x : Int , y : Int -> println(x+y ) }

Модификаторы доступа (модификаторы видимости)

они используются для ограничения использования class , intercaes членов, могут использоваться в методах и классах

публичный, частный, внутренний, защищенный

Общедоступно → можно получить доступ из любого места внутри вашего проекта, в kotlin все является общедоступным, если мы не ограничиваем

private → можно получить доступ только из блока, в котором объявлен член, нельзя получить доступ за пределами области, в которой мы находимся

внутренний → «не в java» делает элемент видимым только внутри файла или модуля, в котором он был реализован

помните, когда мы говорили о наследовании, и мы сказали, что в kotlin все классы являются окончательными, поэтому ни один класс не может наследовать, если мы не сделаем его открытым

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

Вложенный класс и внутренний класс

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

Вложенный класс

он является статическим для класса, поэтому члены внешнего класса могут получить к нему доступ, не создавая объект из

внутренний класс не может получить доступ к членам внешнего класса

class OuterClass {
    private var name : String ="Mohab"

    class InnerClass (){
var jobTitle : String = "Programmer"
        private var age : Int  = 24
        fun printData (){
            println(" iam $name and i work as a  $jobTitle ")
        }
    }
}// error Unresolved reference: name

эта ошибка была из-за того, что внутренний не может получить доступ к внешним членам класса

fun main() {
println(OuterClass.InnerClass().jobTitle)
    OuterClass.InnerClass().printData()
}


class OuterClass {
    private var name : String ="Mohab"

    class InnerClass (){
var jobTitle : String = "Programmer"
        private var age : Int  = 24
        fun printData (){
            println("  i work as a  $jobTitle ")
        }
    }
}

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

fun main() {
println(OuterClass.InnerClass().jobTitle)
    OuterClass.InnerClass().printData()
    var innerObject = OuterClass.InnerClass()
    
}

«внутренний» ключ не может быть создан внутри интерфейсов или не внутренних классов, но он имеет сверхсилу, чем вложенный «он может получить доступ к внешним членам»

class OuterClass {
    private var name : String ="Mohab"

 inner    class InnerClass (){
var jobTitle : String = "Programmer"
        private var age : Int  = 24
        fun printData (){
            println(" hello iam $name i work as a  $jobTitle ")
        }
    }
}// now it works 

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

fun main() {
println(OuterClass().InnerClass().jobTitle)
    OuterClass().InnerClass().printData()
    var innerObject = OuterClass().InnerClass()

}

Обработка исключений

обработка проблем во время выполнения, которые могут возникнуть во время работы программы

Исключение → проблема во время выполнения, из-за которой программа завершает работу, например, число уменьшается на 0, не хватает памяти или нет сети и т. д.

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

Throwable (throw)→ класс, который выдает исключение из котлина или даже исключение нашего собственного типа с помощью ключевого слова (throw), также позволяет нам узнать, где произошла ошибка

try{} → это блок кода {}, в который мы добавляем код, который может вызвать ошибку внутри него, чтобы компилятор пытался сделать все, что в нем есть.

catch(e:Exception){} → всегда следует за блоком try, код внутри которого выполняется только в том случае, если try {} выдал ошибку, поэтому мы говорим компьютеру, поймать эту ошибку и выполнить этот код для обработки

наконец -› сообщает нам, обработал ли компилятор исключение или нет

давайте посмотрим пример исключений

ArithmeticException →когда число уменьшается на 0

ArrayIndexOutOfBoundExceptions →когда мы вызвали индекс, который не существует в массиве

NullPointerException(NPE)→ когда мы использовали нулевое значение

try {}catch(e:ArithmeticException){}

давайте посмотрим пример

fun main() {
    val zero : Int = 0
    val no : Int = 10
    println(no/zero)
    println("I Was Called After Dividng is done ")
}

Исключение в потоке «main» java.lang.ArithmeticException: / на ноль
в MainKt.main(Main.kt:5)
в MainKt.main(Main.kt)

видите, он даже не завершил строку после и не напечатал, но давайте попробуем справиться с этим

fun main() {
    val zero : Int = 0
    val no : Int = 10
try {    println(no/zero)
}catch (e:ArithmeticException){
    println("An Error Occured but it was handled you tried to divide a number by zero")
}
    println("I Was Called After Dividng is done ")
}//output 
//An Error Occured but it was handled you tried to divide a number by zero
//I Was Called After Dividng is done

у нас также может быть n количество обработок исключений, если мы делаем много вещей, которые могут вызвать ошибку

fun main() {
    val zero : Int = 0
    val no : Int = 10
    val myArray = arrayOf("Mohab")
try {
    println(myArray[1])
    println(no/zero)
}catch (e : ArrayIndexOutOfBoundsException){
    println("An Error Occured but it was handled you tried to call an  index is not exist")

}

catch (e:ArithmeticException){
    println("An Error Occured but it was handled you tried to divide a number by zero")
}
    println("I Was Called After Dividng is done ")
}//output 
An Error Occured but it was handled you tried to call an  index is not exist
I Was Called After Dividng is done 

увидеть, что он остановился на первом блоке catch "ArrayIndexOutOfBoundsException"

давайте посмотрим пример, наконец, который будет выполнен с ошибкой или без ошибки

fun main() {
    try {
        println(10 / 5)
    } catch (e: ArithmeticException) {
        println("An Error Occured but it was handled you tried to call an  index is not exist")
    }finally {
        println(" I Will Work anyway ")
    }

}

посмотрим бросим

fun main() {
var myAge : Int = 0
countAge(myAge)
    println("I will be printed  whenever  your func is done ")
}
fun countAge (age : Int ){
    if (age<=0){
        throw CustomException("No one can have negative or zero years")
    }
}
class CustomException(message: String?) : Exception(message) {
}

Исключение в потоке «main» CustomException: никто не может иметь отрицательные или нулевые годы
в MainKt.countAge(Main.kt:10)
в MainKt.main(Main.kt:5)
на MainKt.main(Main.kt)

Это была последняя часть полного руководства по языку программирования kotlin, Ждите следующих руководств

Похлопайте мне, если эта статья действительно вам помогла

Спасибо за прочтение, жду ваших комментариев и ответов…