Swift VS Kotlin

Swift VS Kotlin

Swift和Kotlin作为更加"现代化"的语言,毫无疑问提升了开发原生app的效率,二者旨在与Objective-C和Java互操作,方便"旧"应用的开发进行更新,如果你要从零开始编写一个全新的应用,不要犹豫,选择使用它们,尽情享受它们带来的乐趣。这两个语言有着许多相似之处,让我们来"欣赏"一下吧:

语法差异

print

print("Hello, world!")                              //Swift
println("Hello, world!")                            //Kotlin

变量和常量

var myVariable = 42                                 //Swift
myVariable = 50
let myConstant = 42
var myVariable = 42                                 //Kotlin
myVariable = 50
val myConstant = 42

显示声明

let explicitDouble: Double = 70                     //Swift
val explicitDouble: Double = 70.0                   //Kotlin

隐式声明

let label = "The width is "                         //Swift
let width = 94
let widthLabel = label + String(width)
val label = "The width is "                         //Kotlin
val width = 94
val widthLabel = label + width

字符串插值

let apples = 3                                      //Swift
let oranges = 5
let fruitSummary = "I have \(apples + oranges) " + "pieces of fruit."
val apples = 3                                      //Kotlin
val oranges = 5
val fruitSummary = "I have ${apples + oranges} " + "pieces of fruit."

可选类型

var str: String?                                    //Swift
var str: String?                                    //Kotlin

判空

if str != nil {                                     //Swift
    print("\(str)")
}
//推荐使用
if let str = str {
    print("\(str)")
}
if (str != null) {                                  //Kotlin
    println("$str")
}
//推荐使用
str?.let {
    println("$str")
}

guard

guard let str = str else {                          //Swift
    //do something
}
val id = str ?: run {                               //Kotlin
    //do something
}

可选链式调用

let length = str?.count                             //Swift
val length = str?.length                            //Kotlin

强制解析

let length = str!.count                             //Swift
val length = str!!.length                           //Kotlin

空合运算符

let length = str?.count ?? 0                        //Swift
val length = str?.length ?: 0                       //Kotlin

半开区间运算符

let names = ["Anna", "Alex", "Brian", "Jack"]       //Swift
let count = names.count
for i in 0..<count {
    print("Person \(i + 1) is called \(names[i])") 
}
val names = arrayOf("Anna", "Alex", "Brian", "Jack")//Kotlin
val count = names.count()
for (i in 0 until count) {
    println("Person ${i + 1} is called ${names[i]}")
}

闭区间运算符

for index in 1...5 {                                //Swift
    print("\(index) times 5 is \(index * 5)")
}
for (index in 1..5) {                               //Kotlin
    println("$index times 5 is ${index * 5}")
}

数组

var shoppingList = ["catfish", "water",             //Swift
    "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
val shoppingList = arrayOf("catfish", "water",      //Kotlin
    "tulips", "blue paint")
shoppingList[1] = "bottle of water"

字典

var occupations = [                                 //Swift
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
val occupations = mutableMapOf(                     //Kotlin
    "Malcolm" to "Captain",
    "Kaylee" to "Mechanic"
)
occupations["Jayne"] = "Public Relations"

空集

let emptyArray = [String]()                         //Swift
let emptyDictionary = [String: Float]()
val emptyArray = arrayOf<String>()                  //Kotlin
val emptyMap = mapOf<String, Float>()

函数

func greet(_ name: String,_ day: String) -> String {//Swift
    return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
fun greet(name: String, day: String): String {      //Kotlin
    return "Hello $name, today is $day."
}
greet("Bob", "Tuesday")

元组

func getGasPrices() -> (Double, Double, Double) {   //Swift
    return (3.59, 3.69, 3.79)
}
data class GasPrices(val a: Double, val b: Double,  //Kotlin
     val c: Double)
fun getGasPrices() = GasPrices(3.59, 3.69, 3.79)

可变参数

func sumOf(_ numbers: Int...) -> Int {              //Swift
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf(42, 597, 12)
fun sumOf(vararg numbers: Int): Int {               //Kotlin
    var sum = 0
    for (number in numbers) {
        sum += number
    }
    return sum
}
sumOf(42, 597, 12)

// sumOf() can also be written in a shorter way:
fun sumOf(vararg numbers: Int) = numbers.sum()

函数类型

func makeIncrementer() -> (Int -> Int) {             //Swift
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
let increment = makeIncrementer()
increment(7)
fun makeIncrementer(): (Int) -> Int {               //Kotlin
    val addOne = fun(number: Int): Int {
        return 1 + number
    }
    return addOne
}
val increment = makeIncrementer()
increment(7)

// makeIncrementer can also be written in a shorter way:
fun makeIncrementer() = fun(number: Int) = 1 + number

参数名称

func area(width: Int, height: Int) -> Int {         //Swift
    return width * height
}
area(width: 2, height: 3)
fun area(width: Int, height: Int) = width * height  //Kotlin
area(width = 2, height = 3)

// This is also possible with named arguments
area(2, height = 2)
area(height = 3, width = 2)

声明类

class Shape {                                       //Swift
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
class Shape {                                       //Kotlin
    var numberOfSides = 0
    fun simpleDescription() : String {
        return "A shape with $numberOfSides sides."
    }
}

使用类

var shape = Shape()                                 //Swift
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
var shape = Shape()                                 //Kotlin
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

懒加载

lazy var shape = Shape()                            //Swift
val shape by lazy {Shape()}                         //Kotlin

子类

class NamedShape {                                  //Swift
    var numberOfSides: Int = 0
    let name: String

    init(name: String) {
        self.name = name
    }

    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

class Square: NamedShape {                          
    private var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        self.numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length " + String(sideLength) + "."
    }
}

let test = Square(sideLength: 5.2, name: "square")
test.area()
test.simpleDescription()
open class NamedShape(val name: String) {           //Kotlin
    var numberOfSides = 0

    open fun simpleDescription() =
        "A shape with $numberOfSides sides."
}

class Square(private var sideLength: BigDecimal, name: String) :
        NamedShape(name) {
    init {
        numberOfSides = 4
    }

    fun area() = sideLength.pow(2)

    override fun simpleDescription() =
        "A square with sides of length $sideLength."
}

val test = Square(BigDecimal("5.2"), "square")
test.area()
test.simpleDescription()

类型检查

var movieCount = 0                                  //Swift
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}
var movieCount = 0                                  //Kotlin
var songCount = 0

for (item in library) {
    if (item is Movie) {
        ++movieCount
    } else if (item is Song) {
        ++songCount
    }
}

模式匹配

let nb = 42                                          //Swift
switch nb {
    case 0...7, 8, 9: print("single digit")
    case 10: print("double digits")
    case 11...99: print("double digits")
    case 100...999: print("triple digits")
    default: print("four or more digits")
}
val nb = 42                                         //Kotlin
when (nb) {
    in 0..7, 8, 9 -> println("single digit")
    10 -> println("double digits")
    in 11..99 -> println("double digits")
    in 100..999 -> println("triple digits")
    else -> println("four or more digits")
}

向下转型

for current in someObjects {                        //Swift
    if let movie = current as? Movie {
        print("Movie: '\(movie.name)', " +
            "dir. \(movie.director)")
    }
}
for (current in someObjects) {                      //Kotlin
    if (current is Movie) {
        println("Movie: '${current.name}', " +
	    "dir. ${current.director}")
    }
}

协议

protocol Nameable {                                 //Swift
    func name() -> String
}

func f<T: Nameable>(x: T) {
    print("Name is " + x.name())
}
interface Nameable {                                //Kotlin
    fun name(): String
}

fun <T: Nameable> f(x: T) {
    println("Name is " + x.name())
}

扩展

extension Double {                                  //Swift
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters")
// prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
val Double.km: Double get() = this * 1000           //Kotlin
val Double.m: Double get() = this
val Double.cm: Double get() = this / 100
val Double.mm: Double get() = this / 1000
val Double.ft: Double get() = this / 3.28084

val oneInch = 25.4.mm
println("One inch is $oneInch meters")
// prints "One inch is 0.0254 meters"
val threeFeet = 3.0.ft
println("Three feet is $threeFeet meters")
// prints "Three feet is 0.914399970739201 meters"

其他区别

Kotlin数据类

Kotlin有一个称为数据类的东西,该类在编译时将获得诸如hashCode(),toString()和copy()等方法。可以这样定义:

data class SampleClass(var a: Int = 0, var b: Int = 0, var c: String = "")

Swift没有数据类或任何等效类。

元组

Swift具有元组功能,并且可以为元组设定类型别名;
Kotlin具有Pair和Triple工具类,用于呈现2元和3元组对象,并且可以通过data class模拟自定义元组。

//Swift
typealias SampleTuple = (var1: String, var2: String, var3: String)
//Kotlin
data class SampleTuple(val var1: String, val var2: String, val var3: String) 
// Definition of Pair data class Pair<out A, out B> 
// Definition of Triple data class Triple<out A, out B, out C>

Swift结构体

Swift Struct和Class之间的区别在于,结构体是值类型,而类是引用类型。可将元组视为隐式定义的Struct:

struct SampleStruct {
	var a: Int = 0
	var b: Int = 0
	var c: String = ""
}

Kotlin没有Struct类型。但是,我们可以通过copy函数创建一个新引用:

val sample = SampleClass(1, 1, "Sample") 
val newSample = sample.copy()

我们可以使用Kotlin数据类和Swift结构体来保存数据。即使一个是引用类型,另一个是值类型。

枚举和密封类

Swift和Kotlin都有枚举。但是声明和匹配方式有很大的区别:

enum Game {                                         //Swift
    case regular
    case baseball(Int, String)
    case football(Int, Int, String)
    case basketball(Int, String)
}

func playGame(game: Game) -> Void {
    switch game {
    case .regular:
        print("")
    case .baseball(let inning, let count):
        print("\(inning))  \(count)")
    case .football(let down, let yardsToGo, let timeLeft):
        print("\(down))  \(yardsToGo) \(timeLeft)")
    case .basketball(let quarter, let timeLeft):
        print("\(quarter))  \(timeLeft)")
    }
}

Kotlint通过密封类可以实现枚举。Kotlin的Sealed Class和Swift的Enum之间的唯一区别是,密封类是引用类型,而Swift的Enum是值类型:

sealed class Game {                                 //Kotlin
    object RegularGame: Game()
    class BaseballGame(val inning: Int, val count: String): Game()
    class FootballGame(val down: Int, val yardsToGo: Int, val timeLeft: String): Game()
    class BasketballGame(val quarter: Int, val timeLeft: String): Game()
}

fun playGame(game: Game) {
    when(game) {
        is RegularGame -> println("")
        is BaseballGame -> println("")
        is FootballGame -> println("")
        is BasketballGame -> println("")
    }
}

隐式解包vs lateinit

Swift还具有隐式解包功能,它定义了一个可选内容,但告诉编译器可以展开该内容,因为后面它将会被值。Kotlin也可以通过lateinit关键字执行相同的操作。需要注意的是,作为开发人员,应尽可能避免使用隐式解包方式。

var string: String!                                 //Swift
func doBadStuff() {
   string.doSomething() // Will crash because string doesn’t have a value
}
---------------------
string = “String”
func doGoodStuff() {
   string.doSomething() // This is good because string was set.
}
lateinit var string: String                         //Kotlin
fun doBadStuff() {
   string.doSomething() // Will crash because string doesn’t have a value
}
---------------
string = "String"
fun doGoodStuff() {
    string.doSomething() // This is good because string was set.
}

协议和接口

协议和接口有相同的功能,只是使用了不同的术语。它们定义了一个类在实现接口时必须遵循的一组函数/变量。Kotlin允许在接口的定义中使用泛型,而Swift则可以通过定义关联类型associatedtype来实现。

protocol SampleProtocol {                           //Swift
    associatedtype T
    func get(value: T) -> T
}

extension SampleProtocol where Self.T == Self  {
    func get(value: Self) -> Self {
        // do stuff
    }
}

struct SomeClass: SampleProtocol {
    func get(value: SomeClass) -> SomeClass {
        // do stuff
    }
}
interface SampleInterface<T> {                      //Kotlin
   fun get(value: T): T {
       // do stuff
   }
}

class SomeClass: SampleInterface<Int> {
   override fun get(value: Int): Int {
       // do stuff
   }
}

高阶函数

高阶函数本质上是接受闭包或函数作为参数并返回新值或另一个函数的函数。使用高阶函数,我们可以对值(例如数组)进行转换,过滤和迭代。

func higherOrderFunctions() {                        //Swift
    let array = [1,2,3,4,5,6,7,8,9,10]
    // $0 is implicitly defined as the current value of the spot you are at     in an array
    let mappedArray = array.map {
        $0 * 2
    }
    let filteredArray = array.filter {
        $0 % 2 == 0
    }
    // $0 is not an option because the current value in the closure is now defined as (acc, element)
    let reducedArray = array.reduce(0) { (acc, element) in
        return acc + element
    }
}
fun higherOrderFunctions() {                        //Kotlin
   val array = arrayOf(1,2,3,4,5,6,7,8,9,10)
   // it is implicitly defined as the value of the spot you are at     in an array
   val mappedArray = array.map {
       it * 2
   }
   // result: [2,4,6,8,10,12,14,16,18,20]
   val filteredArray = array.filter {
       it % 2 == 0
   }
   // result: [2,4,6,8,10]
   // it is not an option because the current value in the closure is now defined as acc, element
   val reducedArray = array.reduce { acc, element ->
       acc + element
   }
   // result: 55
}

参考:


本文由Openwit 创作,采用知识共享署名4.0国际许可协议进行许可。
本站文章除注明转载外,均为本站原创或翻译,转载请注明出处。
最后更新于: 2020-03-26

# Kotlin  Swift 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×