7

[Android开发学iOS系列] 语言篇: Swift vs Kotlin - 圣骑士wind

 2 years ago
source link: https://www.cnblogs.com/mengdd/p/swift-vs-kotlin.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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 = 3switch x { case 1: print("x == 1") case 2, 4: print("x == 2 or x == 4") default: print("x is something else") }

Kotlin:

val x = 3when (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()}

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.westdirectionToHead = .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? = nilprint(someString?.count) // print nilprint(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解包过的值, 后面的block只有当它不为nil时才会被执行.

在Kotlin中:

var someString : String? = nullprint(someString?.length) // print nullprint(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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK