Swift vs Kotlin
這篇文章是想著幫助Android開發快速學習Swift編程語言用的. (因為這個文章的作者立場就是這樣.)
我不想寫一個非常長, 非常詳盡的文章, 只是想寫一個快速的版本能讓你快速上手作業.
當然這個文章可能也適合于以下人群:
- 有經驗的其他任何語言的開發者, 想學Swift.
- 一個會Swift的iOS開發者, 想橫向對比, 了解學習一下Kotlin.
- iOS初級程式員, 剛開始學習.
- 用過Swift, 但是有一陣子沒用了, 想快速重繪一下回憶.
基本型別
| Swift | Kotlin |
|---|---|
| Bool | Boolean |
| Array | Array, List, MutableList |
| Set | Set |
| Dictionary | Map |
其他基本型別都是差不多的.
語法
| Swift | Kotlin | |
|---|---|---|
| 變數宣告 | let/var | val/var |
| 具名引數 | at: 0 | at = 0 |
| 函式/方法 | func name() → returnType | fun name(): returnType |
| 表達無值 | nil | null |
| unwrapped type | String! | - |
| if | if number != nil | if(number != null) |
| 為空時提供默認值 | xxx ?? “default string” | ? : ”default string” |
| 不為空時做某件事 | 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 | repeat {} while | do {} while () |
| this instance | self | this |
| value object | struct | data class |
| as? | as? | |
| as! | as | |
| try? | - | |
| try! | - | |
| class initializer | initializer | constructor |
| init a mutable list | var someInts: [Int] = [] | val someInts = mutableListOf |
| init a empty dictionary/map | var namesOfIntegers: [Int: String] = [:] | val namesOfIntegers = mutableMapOf<Int, String>() |
Constants and Variables
Swift:
let不能再次賦值. 如果物件型別是struct, 不能更新物件的任何欄位. 如果是class, 則仍可更新物件的var欄位.var可以給變數重新賦值, 也可以更新變數的var欄位.var可以宣告一個mutable的集合型別.
Kotlin:
val和java中的final等價, 不能再給變數重新賦值, 但是仍然可以更新物件的var欄位.var意味著可以給變數重新賦值.- 集合型別的可變與否是被具體的集合型別宣告所決定的.
Switch case
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")
}
String interpolation
Swift:
var name = "Mike"
print("Hello \(name)")
也可以給String規定格式:
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)
Function and Closure
Swift的function有一個argument label:
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
這里parameterName是方法內部使用的, argumentLabel是被外部呼叫者使用的. (目的是為了增強可讀性.)
當argument label沒有提供的時候, parameter name同時也扮演argument label的角色.
在方法呼叫時argument label 默認是不能省略的(雖然有時候它和parameter name一樣), 如果你想在呼叫的時候省略, 可以用下劃線_明確指明.
Closure
閉包和Kotlin中的lambda相似.
一個簡單的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")
相同點:
- 可以根據背景關系推斷型別, 所以有時候型別可以省略.
- 可以作為另一個函式的引數傳入, 從而實作高階方法.
- 如果閉包/lambda是方法的最后一個引數, 可以提到圓括號外面. 如果是唯一的引數, 可以省略圓括號.
不同點:
- 在Swift中,只有單句運算式可以省略
return關鍵字, 把運算式結果作為回傳值. 而在Kotlin中, 最后的運算式值會被作為回傳結果, 且在lambda中沒有return關鍵字. - Swift有縮略版本的引數名, 比如:
$0,$1,$2.
Custom types
| Swift | Kotlin |
|---|---|
| class | class |
| protocol | interface |
| extension | extension methods |
class
Swift和Kotlin中的類定義和用法十分相似.
繼承是通過:符號, 子類可以override父類的方法.
繼承的的時候父類class需要放在protocol前.
只有構造看起來有點不同, 在Swift中叫initializer:
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}")
struct
struct是一個值型別.
struct和class的區別:
- class可以繼承.
- struct是值型別: 拷貝多份不會共享資料; class是參考型別, 所有的賦值拷貝最終都指向同一份資料實體.
- class有
deinit. - class的實體可以被
let保存, 同時實體的var欄位仍然可被修改, struct則不可修改.
class Person {
var name = "Lily"
}
let p1 = Person()
p1.name = "Justin"
print("\(p1.name)")
這是ok的.
如果Person是struct:
struct Person {
var name = "Lily"
}
let p1 = Person()
p1.name = "Justin"
// Compiler error: Cannot assign to property: `p1` is a `let` constant
編譯器會報錯.
想要改變欄位值, 只能宣告: **var** p1 = Person().
protocol
protocol類似Kotlin中的interface.
我們可以定義一些方法或者計算屬性作為契約.
Properties寫起來是這樣的:
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
}
protocol和interface有一點點小區別: 比如實作protocol的類的方法上不需要使用override關鍵字.
extension
在Swift, extension更像是一個用來放擴展方法和屬性的地方.
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
}
多個case也可以寫在一行, 用逗號分隔:
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
在Swift中使用列舉的時候, 我們可以省略前面的型別, 只用一個.開頭:
var directionToHead = CompassPoint.west
directionToHead = .east
Swift enum有一個allCases屬性, 暴露所有case的集合.
Kotlin:
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
在列舉中我們也可以定義方法和屬性, 這個Swift和Kotlin是一樣的.
Optionals
雖然Swift的optional type和Kotlin的nullable type看起來是類似的(都是具體型別后面加個問號), 但實際上它們還是有點不同.
Swift的optional type更像Java的Optional.
因為你在用之前永遠需要解包(unwrap).
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 = https://www.cnblogs.com/mengdd/p/someString {
print("\(someStringValue) with length \(someStringValue.count)")
}
這里someStringValue是從someString解包過的值, 后面的block只有當它不為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
在Kotlin中, 如果我們判斷過變數不為null, 后面就可以直接用了, 編譯器知道這個變數現在不為空了.
if let 和 guard let
我們上面的例子用if let解包Optional, 只在不為nil的時候執行大括號里面的內容.
guard let做的事情正好相反: else block只在值為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通常被用來做引數檢測, 不合法就return.
并且在guard陳述句之后, number不再是一個optional的型別, 是一個確定有值的型別.
最后
學習新的語言的時候, 不太建議花太多的時間鉆研語言的每個細節.
只需要了解一些最基本的知識, 然后就可以上手做具體的作業和任務.
在實際的任務中進行進一步的學習和練習.
總之, 希望這篇文章對你有用.
References
- Swift book: https://docs.swift.org/swift-book/
出處: 博客園: 圣騎士Wind
Github: https://github.com/mengdd
微信公眾號: 圣騎士Wind
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/499689.html
標籤:iOS
上一篇:iOS 資料存盤
下一篇:iOS 資料存盤
