Swift против Kotlin

Цель этой статьи — помочь разработчику Android быстро освоить язык программирования Swift. (Пишу с этой точки зрения.)

Я не собирался писать очень длинную и подробную статью, чтобы охватить все, просто быстрая статья для того, чтобы вы освоились.

Эта статья также подходит для:

  • Опытный программист (знающий другие языки программирования) хочет изучить Swift.
  • iOS-разработчик (знающий Swift) хочет изучить Kotlin.
  • Начинающих разработчиков iOS.
  • Разработчик давно не использовал Swift и хочет получить краткую памятку.

Основные типы

Swift Kotlin
Bool Boolean
Массив Массив, Список, MutableList
Набор Набор
Словарь Map

Другие типы в основном такие же.

Синтаксис

Swift Kotlin
переменные (не полностью равнозначны, см. пояснения ниже) let/var val/var
именованные аргументы в: 0 at = 0
функция func name() → returnType fun name(): returnType
отсутствие значения nil нуль
развёрнутый тип Строка!
если если число != nil if(number != null)
предоставьте значение по умолчанию, если nil или null xxx ?? «строка по умолчанию» ? : «строка по умолчанию»
если значение есть, сделайте {} if let number = Int(«333») {} ?.let {}
for loop for i in 1…5 {} for (i in 1..5) {}
for loop for i in 1…<5 {} for (i in 1 until 5) {}
do while loop повторять {} while do {} while ()
данный экземпляр self этот
объект значения структура класс данных
как? как?
как! as
попробовать?
попробовать!
инициализатор класса инициализатор конструктор
инициализация изменяемого списка var someInts: [Int] = [] val someInts = mutableListOf()
инициализация пустого словаря/карты var namesOfIntegers: [Int: String] = [:] val namesOfIntegers = mutableMapOf()

Константы и переменные

Swift:

Kotlin:

  • Неизменяемость или изменяемость типов коллекций контролируется типом данных.

Случай Switch

Swift:

var x = 3
switch x {
    case 1: print("x == 1")
    case 2, 4: print("x == 2 or x == 4")
    default: print("x is something else")  
}
Войти в полноэкранный режим Выход из полноэкранного режима

Kotlin:

val x = 3
when (x) {
    1 -> print("x == 1")
    2, 4 -> print("x == 2 or x == 4")
    else -> print("x is something else")
}
Войти в полноэкранный режим Выход из полноэкранного режима

Интерполяция строк

Swift:

var name = "Mike"
print("Hello (name)")
Войти в полноэкранный режим Выход из полноэкранного режима

Строка также может быть выведена в формате:

let str = NSString(format:"%d , %f, %ld, %@", 1, 1.5, 100, "Hello World")
print(str)
Войти в полноэкранный режим Выйти из полноэкранного режима

Kotlin:

var name = "Mike"
println("Hello $name")

val str = String.format("%d, %f, %d, %s", 1, 1.5, 100, "Hello World")
print(str)
Войти в полноэкранный режим Выйти из полноэкранного режима

Функция и закрытие

Функция Swift имеет метку аргумента:

func someFunction(argumentLabel parameterName: Int) {
    // In the function body, parameterName refers to the argument value
    // for that parameter.
}
Enter fullscreen mode Выйти из полноэкранного режима

В то время как parameterName используется внутри функции, argumentLabel используется вызывающей стороной.

Если метка аргумента не указана, parameterName также играет роль метки аргумента.

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

Closure

Closure похож на лямбду в Kotlin.

Простой пример на Swift:

let sayHello = { (name: String) -> String in
    let result = "Hello (name)"
    print(result)
    return result
}

sayHello("Mike")
Вход в полноэкранный режим Выйти из полноэкранного режима

Сделайте то же самое в Kotlin:

val sayHello : (String) -> String = { name: String -> 
    val result = "Hello $name"
    print(result)
    result
}

sayHello("Mike")
Войти в полноэкранный режим Выйти из полноэкранного режима

Общие:

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

Различия:

  • В Swift только закрытие одного выражения может опускать ключевое слово return; в Kotlin последнее выражение будет рассматриваться как возвращаемое значение, ключевое слово return в лямбде отсутствует.
  • В Swift есть сокращенные имена аргументов, такие как $0, $1, $2.

Пользовательские типы

Swift Kotlin
класс класс
протокол интерфейс
расширение методы расширения

класс

Класс в Swift и Kotlin выглядит совершенно одинаково.

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

Существует требование порядка: класс должен быть помещен перед любыми протоколами.

Единственное, что отличается — это конструктор, в swift это инициализатор:

class Person {
    let name: String
    init(name: String = "") {
        self.name = name
    }
}
let p1 = Person()
print("(p1.name)") // default name: ""

let p2 = Person(name: "haha")
print("(p2.name)")
Вход в полноэкранный режим Выйти из полноэкранного режима

В Kotlin мы могли бы достичь того же результата, написав так:

class Person(val name: String = "") {
}
val p1 = Person()
print("${p1.name}") // default name: ""

val p2 = Person(name="haha")
print("${p2.name}")
Enter fullscreen mode Выйти из полноэкранного режима

struct

Структура — это тип значения.

struct отличается от класса:

  • класс может наследоваться.
  • struct — тип значения, копии никогда не делятся данными; class — ссылочный тип, все копии будут иметь один и тот же экземпляр.
  • класс имеет deinit.
  • экземпляр класса может быть let , и вы можете изменить свойство var класса.
class Person {
    var name = "Lily"
}

let p1 = Person()
p1.name = "Justin"

print("(p1.name)")
Вход в полноэкранный режим Выход из полноэкранного режима

Это нормально.

Но если Person является структурой:

struct Person {
    var name = "Lily"
}

let p1 = Person()
p1.name = "Justin"
// Compiler error: Cannot assign to property: `p1` is a `let` constant
Войти в полноэкранный режим Выход из полноэкранного режима

При использовании struct, мы должны использовать **var** p1 = Person().

протокол

Протокол — это то же самое, что interface в Kotlin.

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

Свойствами могут быть:

protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Есть небольшие различия между протоколом и интерфейсом, например, классу, реализующему протокол, не нужно использовать ключевое слово override в функциях.

расширение

Расширение также отличается. В Swift расширение больше похоже на место для хранения функций и свойств.

extension String {
    func trimmed() -> String {
        self.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    mutating func trim() {
        self = self.trimmed()
    }

    var lines: [String] {
        self.components(separatedBy: .newlines)
    }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

В Kotlin метод расширения может быть методом верхнего уровня, просто добавьте тип перед .:

fun String.someMethod() : String {
    return this.trim()
}
Вход в полноэкранный режим Выход из полноэкранного режима

enum

Swift enum:

enum CompassPoint {
    case north
    case south
    case east
    case west
}
Вход в полноэкранный режим Выход из полноэкранного режима

Несколько случаев могут быть помещены в одну строку, разделенные запятой:

enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
Войти в полноэкранный режим Выйти из полноэкранного режима

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

var directionToHead = CompassPoint.west
directionToHead = .east
Enter fullscreen mode Выйти из полноэкранного режима

Swift enum имеет свойство allCases, которое раскрывает коллекцию всех случаев.

Kotlin:

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}
Войти в полноэкранный режим Выход из полноэкранного режима

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

Опции

Хотя синтаксис опционального типа в Swift и типа nullable в Kotlin выглядит похоже (вопросительный знак после типа), они отличаются.

Опциональный тип в Swift больше похож на Optional в Java.

Вам всегда нужно развернуть его перед использованием значения.

var someString : String? = nil
print(someString?.count) // print nil
print(someString!.count) // Fatal error: Unexpectedly found nil while unwrapping an Optional value
Вход в полноэкранный режим Выход из полноэкранного режима

Когда переменная имеет значение, мы хотим его использовать:

var someString : String? = "Hello"

if (someString != nil) {
    print("(someString) with length (someString?.count)")
    // print: Optional("Hello") with length Optional(5)

    print("(someString!) with length (someString!.count)")
    // print: Hello with length 5
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что при прямом использовании переменная всегда будет Optional.

На самом деле в Swift есть более простой способ сделать это, используя if let:

if let someStringValue = someString {
    print("(someStringValue) with length (someStringValue.count)")
}
Войти в полноэкранный режим Выйти из полноэкранного режима

someStringValue — это развернутое значение из someString, и блок вводится только тогда, когда оно не nil.

В Kotlin:

var someString : String? = null
print(someString?.length) // print null
print(someString!!.length) // NullPointerException
Войти в полноэкранный режим Выход из полноэкранного режима

Разница в основном в том, когда переменная имеет значение:

var someString : String? = "Hello"
if(someString != null) {
   print("$someString with length: ${someString.length}")  
}
// print: Hello with length: 5
Enter fullscreen mode Выйти из полноэкранного режима

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

If let и guard let

Как мы видим в примере выше в разделе Optional, if let может развернуть значение Optional и выполнить блок только тогда, когда оно имеет значение.

А guard let делает обратное: блок else будет введен только тогда, когда значение равно nil .

func printSquare(of number: Int?){
    guard let number = number else {
        print("Oops we got nil")
        return
    }

    print("(number) * (number) is (number * number)")
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

После guard let число больше не является необязательным, оно имеет значение.

Последнее замечание

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

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

В любом случае, я надеюсь, что эта статья будет для вас полезной и нужной.

Ссылки

  • Книга по Swift: https://docs.swift.org/swift-book/

Оцените статью
devanswers.ru
Добавить комментарий