Сравнение Swift vs Kotlin
28.11.2018Небольшая табличка сравнения кода на Swift и кода на Kotlin для справки. Этакий cheet sheet.
Переменные и константы
Swift
let a: Int = 10
var b: Int = 20
Kotlin
val a: Int = 10
var b: Int = 20
Optionals
Swift
let some: Something? = nil
var some: Something? = Something(text: "Hello")
// optional chaining
let greeting = some?.greet()
// elvis
let value = some?.value ?? 30
// optional unwraping
if let some = some {
print(some) // some is not optional
}
// force unwraping
let forced = some!
Kotlin
val some: Something? = nil
var some: Something? = Something("Hello")
// optional chaining
val greeting = some?.greet()
// elvis
val value = some?.value ?: 30
// optional unwraping
some?.let { some -> // it if name is not provided
print(some) // some is not optional
}
if (some != null) {
print(some) // some is smart casted and not optional
}
// force unwraping
val forced = some!!
Форматирование кода
Скобки (круглые и фигурные)
Swift
- Круглые - не обязательны
- Фигурные - обязательны
let str = "Hello, Swift"
func increse(_ value: Int) -> Int {
return value + 1
}
func statements() {
var i = 0
while i < 10 {
i = increase(i)
if str == "something" {
print(str)
}
}
}
Kotlin
- Круглые - обязательны
- Фигурные - не обязательны
val str = "Hello, Kotlin"
fun increase(value: Int): Int = value + 1
fun statements() {
var i = 0
while (i < 10) i = increase(i)
if (str == "something") print(str)
}
Управляющие конструкции
Pattern Matching
Swift
let number = 42
switch number {
case 0...7, 8, 9: print("1 digit")
case 10: print("2 digits")
case 11...99: print("2 digits")
case 100...999: print("3 digits")
default: print("4 or more digits")
}
Kotlin
val number = 42
when (number) {
in 0..7, 8, 9 -> println("1 digit")
10 -> println("2 digits")
in 11..99 -> println("2 digits")
in 100..999 -> println("3 digits")
else -> println("4 or more digits")
}
if, when = expressions, not statements (!)
Swift
- Не применимо
Kotlin
val test = if (true) "Test" else "False"
val state = State.Off
fun decide() = when(state) {
State.Off -> "Off"
State.On -> "On"
}
val decision = decide()
Типы
Любой тип
Swift
let a: Any = "Hello"
let b: AnyObject = SomeClass()
Kotlin
val a: Any = "Hello"
// no AnyObject yet
Строковая интерполяция
Swift
let str = "Hello \(nickname)"
let str2 = "Hello \(user.nickname)"
Kotlin
val str = "Hello $nickname"
val str2 = "Hello ${user.nickname}"
Интервалы (Ranges)
Swift
let rng1 = 0...10
let rng2 = 0..<10
Kotlin
val rng1 = 0..10
// no rng2
Коллекции
Swift
let stringArray = [String]()
// no stringList
let stringFloatMap = [String: Float]()
let stringSet = Set<String>()
var countries: [String] = ["Switzerland", "France", "Germany"]
countries.append("Italy")
countries.remove("France")
var jobs: [String: String] = [
"Roger": "CEO",
"Martin": "CTO"
]
jobs["Adrian"] = "Writer"
Kotlin
- Нельзя использовать [] для инициализации массива, используется arrayOf
- в arrayOf добавлять и удалять элементы нельзя, можно только их менять
val stringArray = arrayOf<String>()
val stringList = listOf<String>()
val stringFloatMap = mapOf<String, Float>()
val stringSet = setOf<String>()
val countries = mutableListOf<String>("Switzerland", "France", "Germany")
countries.add("Italy")
countries.remove("France")
val jobs = mutableMapOf(
"Roger" to "CEO",
"Martin" to "CTO"
)
jobs["Adrian"] = "Writer"
Итерирование коллекций
Swift
for str in stringArray {}
for (index, str) in stringArray.enumerated() {}
// no for str in stringList
for (str, num) in stringFloatMap {}
for str in stringSet {}
Kotlin
for (str in stringArray) {}
for (str in stringList) {}
for ((str, num) in stringFloatMap) {}
for (str in stringSet) {}
Процедурное программирование
Процедуры и функции
Swift
func method1(input: String) -> Int {
return input.count
}
// no method2
func method3<T>(input: T) -> String {
return String(describing: input)
}
Kotlin
fun method1(input: String): Int {
return input.length
}
fun method2(input: String) = input.length
fun <T>method3(input: T) = input.toString()
ООП
Интерфейсы
Swift
protocol Person {
var name: String { get set }
func greet() -> String
func showMoreInformation()
}
extension Person {
func greet() -> String {
return "Hello! I am \(self)"
}
}
Kotlin
interface Person {
var name: String
get set
fun greet() = "Hello! I am $this"
fun showMoreInformation()
}
Конструкторы
Swift
class Manager: Person {
var backingName: String
var staff: [Person]
var state: State
let isActive: Bool
init(backingName = "": String, staff: [Person] = [], state: State = .off) {
self.backingName = backingName
self.staff = staff
self.state = state
self.isActive = true
}
Kotlin
class Manager(private var backingName: String = "",
private var staff: MutableList<Person> = mutableListOf<Person>(),
var state: State = State.Off) : Person {
private val isActive: Boolean
init {
isActive = true
}
}
Data Classes (PONSO/POSS vs POJO)
Swift
struct Employee {
let backingName: String
let age: Int
init(backingName: String = "", age: Int = 30) {
self.backingName = backingName
self.age = age
}
}
Kotlin
data class Employee(private var backingName: String = "",
var age: Int = 30) : Person {
Инстанцирование объектов
Swift
let person = Employee(
name: "Olivia",
age: 45
)
Kotlin
val person1 = Employee("Olivia", 45)
val person2 = Employee().apply {
name = "Thomas"
age = 56
}
Расширения классов
Swift
extension Double {
var fahrenheit: Double {
(self * 9 / 5) + 32
}
var celsius: Double {
(self - 32) * 5 / 9
}
}
let temperature = Double(32.0)
let fahrenheit = temperature.fahrenheit
let celsius = fahrenheit.celsius
print("\(temperature) degrees Celsius is \(fahrenheit) degrees Fahrenheit")
Kotlin
val Double.fahrenheit: Double get() = (this * 9 / 5) + 32
val Double.celsius: Double get() = (this - 32) * 5 / 9
val temperature: Double = 32.0
val fahrenheit = temperature.fahrenheit
val celsius = fahrenheit.celsius
println("$temperature degrees Celsius is $fahrenheit degrees Fahrenheit")
Простые объекты и Singleton’ы
Swift
enum Constants {
static let PI = 3.14
static let ANSWER = 42
static func name() -> String {
return "Math constants"
}
}
Kotlin
object Constants {
val PI = 3.14
val ANSWER = 42
fun name() = "Math contstants"
}
Объекты-компаньоны
Swift
- Просто используйте static (class) члены
Kotlin
- В Kotlin нет статических членов
companion object OptionalName {
val MAXIMUM_EMPLOYEE_COUNT = 10
fun managerFactory() = Manager("Maria Hill")
}
Перегрузка операторов
Swift
- Можно делать свои операторы (например квадратный корень)
func + (lhs: Person, rhs: Person) -> Team {
return Team(lhs, rhs)
}
let team = manager + person
Kotlin
operator fun plus(person: Person): Team {
return Team(this, person)
}
val team = manager + person
Инфиксные методы
Swift
- Не применимо
Kotlin
infix fun addPerson(person: Person) {
if (staff.count() < MAXIMUM_EMPLOYEE_COUNT) {
staff.add(person)
}
else {
throw Exception("Cannot add more staff members")
}
}
manager addPerson person
Перечисления
Swift
enum State {
case on
case off
var desc: String { ... }
func notify() { ... }
}
Kotlin
enum class State {
On, Off
var desc: String { ... }
func notify() = ...
}
Резюмирующая табличка
Kotlin 1.2 | Objective-C 2.0 | Swift 4 | |
---|---|---|---|
Наследование | Одинарное, с интерфейсами и расширениями | Одинарное, с протоколами | Одинарное, с протоколами и расширениями |
Точки с запятой ; |
Не обязательны | Обязательны | Не обязательны |
Объявление класса | class |
@interface & @implementation |
class |
Интерфейсы | реализует interface |
поддерживает @protocol |
поддерживает protocol |
Подключение кода | import (символы) |
#import (файлы) |
import (символы) |
Расширение классов | Расширения | Категории | Расширения |
Динамическая типизация | Any |
id |
Any |
Суффикс приватных полей | Не используется | _ (подчеркивание) |
_ (подчеркивание) |
Управление памятью | Сборка мусора (GС) | Ручное или автоматическое управление памятью (MRC vs ARC) | Автоматическое управление памятью (ARC) |
Дженерики | да (type erasure) | да (type erasure) | да |
Указатели на метод | нет | @selector |
#selector |
Обратный вызов (callbacks) | Лямбды | Делегаты и блоки | замыкания |
Указатели | нет | да | Через библиотечные классы |
Корневые классы | Object |
NSObject / NSProxy / … |
NSObject / NSProxy / … |
Управление областью видимости | public / internal / protected / private |
@public / @protected / @private (только поля) |
open / public / internal / fileprivate / private |
Обработка ошибок | try / catch / finally + Exception |
@try / @catch / @finally + NSException |
do / try / catch + Error |
Пространства имен | Пакеты | Через префиксы классов | Неявные, через модули |
Грамматика | kotlinlang.org | developer.apple.com |