Swift 语法学习指南 - 与 Kotlin 对比

本指南专为有 Android/Kotlin 开发经验的开发者设计,通过对比学习快速掌握 Swift 语法

目录

  1. 语言基础对比
  2. 变量与常量
  3. 数据类型
  4. 函数定义
  5. 类与结构体
  6. 继承与协议
  7. 可选类型
  8. 集合类型
  9. 控制流
  10. 闭包与Lambda
  11. 扩展与Extension
  12. 错误处理
  13. 内存管理
  14. 实战练习

语言基础对比

基本特性对比

特性SwiftKotlin
类型推断✅ 强类型推断✅ 强类型推断
空安全✅ Optional 类型✅ Nullable 类型
函数式编程✅ 支持✅ 支持
面向对象✅ 支持✅ 支持
协议/接口ProtocolInterface
扩展ExtensionExtension Function

变量与常量

Swift

// 常量 - 不可变
let name = "张三"           // 类型推断
let age: Int = 25          // 显式类型// 变量 - 可变
var score = 90
var height: Double = 175.5// 延迟初始化
lazy var expensiveResource = createResource()

Kotlin

// 常量 - 不可变
val name = "张三"           // 类型推断
val age: Int = 25          // 显式类型// 变量 - 可变
var score = 90
var height: Double = 175.5// 延迟初始化
val expensiveResource by lazy { createResource() }

对比总结

  • Swift 使用 let/var,Kotlin 使用 val/var
  • 两者都支持类型推断
  • Swift 的 lazy 是关键字,Kotlin 使用 by lazy 委托

数据类型

基本数据类型对比

类型SwiftKotlin
整数Int, Int8, Int16, Int32, Int64Int, Byte, Short, Int, Long
浮点Float, DoubleFloat, Double
布尔BoolBoolean
字符CharacterChar
字符串StringString

字符串操作

Swift
// 字符串插值
let name = "Swift"
let message = "Hello, \(name)!"// 多行字符串
let multiline = """
这是一个
多行字符串
"""// 字符串方法
let text = "Hello World"
print(text.count)                    // 长度
print(text.uppercased())            // 大写
print(text.contains("World"))       // 包含
Kotlin
// 字符串插值
val name = "Kotlin"
val message = "Hello, $name!"
val complexMessage = "Hello, ${name.uppercase()}!"// 多行字符串
val multiline = """这是一个多行字符串
""".trimIndent()// 字符串方法
val text = "Hello World"
println(text.length)                 // 长度
println(text.uppercase())           // 大写
println(text.contains("World"))     // 包含

协议属性声明详解

为什么协议中必须使用 var 而不是 let

Swift 协议中的属性声明有特殊的语法规则:

1. 协议属性声明规则
protocol MyProtocol {// ✅ 正确:只读属性var readOnlyProperty: String { get }// ✅ 正确:可读写属性var readWriteProperty: Int { get set }// ❌ 错误:协议中不能使用 let// let constantProperty: String { get }  // 编译错误
}
2. 实现协议时的灵活性
class MyClass: MyProtocol {// 只读属性可以用 let 实现let readOnlyProperty: String = "Hello"// 也可以用 var 实现var anotherReadOnly: String {return "World"}// 可读写属性必须用 var 实现var readWriteProperty: Int = 42
}
3. 与 Kotlin 的对比
特性Swift 协议Kotlin 接口
只读属性声明var property: Type { get }val property: Type
可读写属性声明var property: Type { get set }var property: Type
实现只读属性可用 letvar可用 valvar
实现可读写属性必须用 var必须用 var
4. 核心要点
  • 协议声明:Swift 协议中所有属性都必须用 var 声明
  • 访问控制:通过 { get }{ get set } 指定属性的访问权限
  • 实现灵活性:只读属性({ get })在实现时可以是 let 常量
  • 类型安全:编译器确保实现类满足协议的访问权限要求

这种设计让 Swift 协议既保持了灵活性,又确保了类型安全。


函数定义

Swift

// 基本函数
func greet(name: String) -> String {return "Hello, \(name)!"
}// 带默认参数
func greet(name: String, age: Int = 18) -> String {return "Hello, \(name), you are \(age) years old"
}// 可变参数
func sum(_ numbers: Int...) -> Int {return numbers.reduce(0, +)
}// 高阶函数
func processData(_ data: [Int], processor: (Int) -> Int) -> [Int] {return data.map(processor)
}// 调用
let result1 = greet(name: "张三")
let result2 = greet(name: "李四", age: 25)
let total = sum(1, 2, 3, 4, 5)

Kotlin

// 基本函数
fun greet(name: String): String {return "Hello, $name!"
}// 带默认参数
fun greet(name: String, age: Int = 18): String {return "Hello, $name, you are $age years old"
}// 可变参数
fun sum(vararg numbers: Int): Int {return numbers.sum()
}// 高阶函数
fun processData(data: List<Int>, processor: (Int) -> Int): List<Int> {return data.map(processor)
}// 调用
val result1 = greet("张三")
val result2 = greet("李四", 25)
val total = sum(1, 2, 3, 4, 5)

对比总结

  • Swift 使用 func 关键字,Kotlin 使用 fun
  • Swift 参数标签更灵活,Kotlin 相对简单
  • Swift 可变参数用 ...,Kotlin 用 vararg

类与结构体

Swift

// 结构体(值类型)
struct Point {var x: Doublevar y: Double// 计算属性var distance: Double {return sqrt(x * x + y * y)}// 方法// mutating 关键字说明:// 在 Swift 中,结构体(struct)是值类型,默认情况下其方法不能修改实例的属性// 如果需要在方法中修改结构体的属性,必须使用 mutating 关键字标记该方法// 这是 Swift 的安全机制,确保值类型的不可变性,除非明确声明为可变mutating func moveBy(x deltaX: Double, y deltaY: Double) {x += deltaX  // 修改实例属性 xy += deltaY  // 修改实例属性 y}
}// 类(引用类型)
class Person {var name: Stringvar age: Int// 构造器init(name: String, age: Int) {self.name = nameself.age = age}// 方法func introduce() -> String {return "我是\(name),今年\(age)岁"}
}// 使用
var point = Point(x: 3.0, y: 4.0)
print(point.distance)  // 5.0
point.moveBy(x: 1.0, y: 1.0)let person = Person(name: "张三", age: 25)
print(person.introduce())

Kotlin

// 数据类(类似结构体)
data class Point(var x: Double,var y: Double
) {// 计算属性val distance: Doubleget() = sqrt(x * x + y * y)// 方法fun moveBy(deltaX: Double, deltaY: Double) {x += deltaXy += deltaY}
}// 类
class Person(var name: String,var age: Int
) {// 方法fun introduce(): String {return "我是$name,今年${age}岁"}
}// 使用
val point = Point(3.0, 4.0)
println(point.distance)  // 5.0
point.moveBy(1.0, 1.0)val person = Person("张三", 25)
println(person.introduce())

mutating 关键字详解

Swift 中的 mutating

mutating 是 Swift 中一个重要的关键字,专门用于值类型(struct 和 enum):

struct Counter {var count = 0// ❌ 错误:不能在非 mutating 方法中修改属性// func increment() {//     count += 1  // 编译错误// }// ✅ 正确:使用 mutating 关键字mutating func increment() {count += 1  // 可以修改属性}mutating func reset() {count = 0}// 不修改属性的方法不需要 mutatingfunc getCurrentCount() -> Int {return count}
}// 使用示例
var counter = Counter()  // 注意:必须是 var,不能是 let
counter.increment()      // count = 1
counter.increment()      // count = 2
print(counter.getCurrentCount())  // 2// let counter2 = Counter()
// counter2.increment()  // ❌ 编译错误:let 常量不能调用 mutating 方法
与 Kotlin 的对比
特性SwiftKotlin
值类型可变性需要 mutating 关键字明确标记直接修改,无需特殊标记
编译时检查严格检查,防止意外修改相对宽松
常量实例let 实例不能调用 mutating 方法val 实例仍可修改内部可变属性
安全性更高的类型安全性依赖开发者自觉
为什么需要 mutating?
  1. 值类型的不可变性:Swift 的 struct 是值类型,默认不可变
  2. 明确的意图表达mutating 明确表示该方法会修改实例
  3. 编译时安全:防止意外修改,提高代码安全性
  4. 函数式编程支持:鼓励不可变编程风格
实际应用场景
struct BankAccount {private var balance: Doubleinit(initialBalance: Double) {self.balance = initialBalance}// 查询余额 - 不需要 mutatingfunc getBalance() -> Double {return balance}// 存款 - 需要 mutatingmutating func deposit(amount: Double) {guard amount > 0 else { return }balance += amount}// 取款 - 需要 mutatingmutating func withdraw(amount: Double) -> Bool {guard amount > 0 && amount <= balance else {return false}balance -= amountreturn true}
}var account = BankAccount(initialBalance: 1000.0)
print(account.getBalance())  // 1000.0
account.deposit(amount: 500.0)
print(account.getBalance())  // 1500.0
let success = account.withdraw(amount: 200.0)
print(account.getBalance())  // 1300.0

继承与协议

Swift

// 协议定义
protocol Drawable {func draw()// 注意:协议中的属性声明必须使用 var,不能使用 let// { get } 表示这是一个只读属性,实现时可以是 let 常量或 var 变量// 但在协议声明中必须用 var,因为协议不知道具体实现方式var area: Double { get }
}protocol Colorable {// { get set } 表示这是一个可读写属性,实现时必须是 var 变量var color: String { get set }
}// 基类
class Shape: Drawable {var area: Double {return 0.0}func draw() {print("绘制形状")}
}// 继承和协议实现
class Circle: Shape, Colorable {var radius: Doublevar color: Stringinit(radius: Double, color: String) {self.radius = radiusself.color = colorsuper.init()}override var area: Double {return Double.pi * radius * radius}override func draw() {print("绘制\(color)的圆形")}
}

Kotlin

// 接口定义
interface Drawable {fun draw()val area: Double
}interface Colorable {var color: String
}// 基类
open class Shape : Drawable {override val area: Doubleget() = 0.0override fun draw() {println("绘制形状")}
}// 继承和接口实现
class Circle(val radius: Double,override var color: String
) : Shape(), Colorable {override val area: Doubleget() = Math.PI * radius * radiusoverride fun draw() {println("绘制${color}的圆形")}
}

可选类型

Swift Optional

// 可选类型声明
var optionalName: String? = "张三"
var optionalAge: Int? = nil// 可选绑定
if let name = optionalName {// \(name) 是字符串插值,name 是变量调用// 在字符串插值中可以调用属性、方法和扩展函数print("姓名是: \(name)")print("姓名长度: \(name.count)")  // 调用属性print("大写姓名: \(name.uppercased())")  // 调用方法
} else {print("姓名为空")
}// guard 语句
func processUser(name: String?) {guard let userName = name else {print("用户名不能为空")return}print("处理用户: \(userName)")
}// 空合并运算符
let displayName = optionalName ?? "未知用户"// 强制解包(危险操作)
let forcedName = optionalName!  // 如果为nil会崩溃// 可选链
class Person {var address: Address?
}class Address {var street: String?
}let person: Person? = Person()
let street = person?.address?.street  // 可选链调用

Kotlin Nullable

// 可空类型声明
var optionalName: String? = "张三"
var optionalAge: Int? = null// 安全调用
optionalName?.let { name ->println("姓名是: $name")
} ?: run {println("姓名为空")
}// Elvis 运算符
val displayName = optionalName ?: "未知用户"// 非空断言(危险操作)
val forcedName = optionalName!!  // 如果为null会抛异常// 安全调用链
class Person {var address: Address? = null
}class Address {var street: String? = null
}val person: Person? = Person()
val street = person?.address?.street  // 安全调用链

对比总结

  • Swift 使用 ?!,Kotlin 也使用 ?!!
  • Swift 的 if let 对应 Kotlin 的 ?.let
  • Swift 的 ?? 对应 Kotlin 的 ?:

字符串插值与扩展函数调用

回答你的问题:是的,\(name) 是对变量的调用,而且在字符串插值中可以调用属性、方法和扩展函数。

Swift 字符串插值
let name = "张三"
let age = 25// 基本变量调用
print("姓名: \(name)")// 调用属性和方法
print("姓名长度: \(name.count)")
print("大写姓名: \(name.uppercased())")
print("年龄加10: \(age + 10)")// 调用扩展函数
extension String {func addPrefix(_ prefix: String) -> String {return prefix + self}
}print("带前缀的姓名: \(name.addPrefix("Mr. "))")// 复杂表达式
print("信息: \(name.isEmpty ? "无名" : name.uppercased())")
Kotlin 字符串模板
val name = "张三"
val age = 25// 基本变量调用
println("姓名: $name")// 调用属性和方法
println("姓名长度: ${name.length}")
println("大写姓名: ${name.uppercase()}")
println("年龄加10: ${age + 10}")// 调用扩展函数
fun String.addPrefix(prefix: String): String {return prefix + this
}println("带前缀的姓名: ${name.addPrefix("Mr. ")}")// 复杂表达式
println("信息: ${if (name.isEmpty()) "无名" else name.uppercase()}")
对比总结
特性SwiftKotlin
基本语法\(variable)$variable
复杂表达式\(expression)${expression}
方法调用\(obj.method())${obj.method()}
扩展函数\(obj.extensionFunc())${obj.extensionFunc()}
条件表达式\(condition ? a : b)${if (condition) a else b}
核心要点
  • 变量调用:字符串插值中的变量是正常的变量访问
  • 方法链式调用:可以在插值中进行链式方法调用
  • 扩展函数支持:完全支持调用扩展函数
  • 表达式计算:插值内可以进行复杂的表达式计算
  • 类型安全:编译时检查确保类型正确

集合类型

Swift

// 数组
var numbers = [1, 2, 3, 4, 5]
var strings: [String] = ["a", "b", "c"]// 数组操作
numbers.append(6)
numbers.insert(0, at: 0)
let first = numbers.first  // Optional<Int>
let count = numbers.count// 字典
var scores = ["张三": 95, "李四": 87]
var ages: [String: Int] = [:]// 字典操作
scores["王五"] = 92
let zhangScore = scores["张三"]  // Optional<Int>// 集合
var uniqueNumbers: Set<Int> = [1, 2, 3, 3, 4]  // {1, 2, 3, 4}// 高阶函数
let doubled = numbers.map { $0 * 2 }
let evens = numbers.filter { $0 % 2 == 0 }
let sum = numbers.reduce(0, +)

Kotlin

// 列表
val numbers = mutableListOf(1, 2, 3, 4, 5)
val strings: List<String> = listOf("a", "b", "c")// 列表操作
numbers.add(6)
numbers.add(0, 0)
val first = numbers.firstOrNull()  // Int?
val count = numbers.size// 映射
val scores = mutableMapOf("张三" to 95, "李四" to 87)
val ages: MutableMap<String, Int> = mutableMapOf()// 映射操作
scores["王五"] = 92
val zhangScore = scores["张三"]  // Int?// 集合
val uniqueNumbers: Set<Int> = setOf(1, 2, 3, 3, 4)  // {1, 2, 3, 4}// 高阶函数
val doubled = numbers.map { it * 2 }
val evens = numbers.filter { it % 2 == 0 }
val sum = numbers.reduce { acc, n -> acc + n }

控制流

Swift

// if-else
let score = 85
if score >= 90 {print("优秀")
} else if score >= 80 {print("良好")
} else {print("需要努力")
}// switch
let grade = "A"
switch grade {case "A":print("优秀")case "B", "C":print("良好")case "D":print("及格")default:print("不及格")
}// for 循环
for i in 1...5 {print(i)
}for i in 1..<5 {print(i)  // 1, 2, 3, 4
}for (index, value) in ["a", "b", "c"].enumerated() {print("\(index): \(value)")
}// while 循环
var count = 0
while count < 5 {print(count)count += 1
}

Kotlin

// if-else
val score = 85
if (score >= 90) {println("优秀")
} else if (score >= 80) {println("良好")
} else {println("需要努力")
}// when (类似 switch)
val grade = "A"
when (grade) {"A" -> println("优秀")"B", "C" -> println("良好")"D" -> println("及格")else -> println("不及格")
}// for 循环
for (i in 1..5) {println(i)
}for (i in 1 until 5) {println(i)  // 1, 2, 3, 4
}for ((index, value) in listOf("a", "b", "c").withIndex()) {println("$index: $value")
}// while 循环
var count = 0
while (count < 5) {println(count)count++
}

闭包与Lambda

Swift 闭包

// 基本闭包语法
let numbers = [1, 2, 3, 4, 5]// 完整语法
let doubled1 = numbers.map({ (number: Int) -> Int inreturn number * 2
})// 简化语法
let doubled2 = numbers.map { number inreturn number * 2
}// 最简语法
let doubled3 = numbers.map { $0 * 2 }// 尾随闭包
let filtered = numbers.filter { $0 % 2 == 0 }// 捕获值
func makeIncrementer(incrementAmount: Int) -> () -> Int {var total = 0let incrementer: () -> Int = {total += incrementAmountreturn total}return incrementer
}let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo())  // 2
print(incrementByTwo())  // 4

Kotlin Lambda

// 基本 Lambda 语法
val numbers = listOf(1, 2, 3, 4, 5)// 完整语法
val doubled1 = numbers.map({ number: Int -> number * 2 })// 简化语法
val doubled2 = numbers.map { number -> number * 2 }// 最简语法(使用 it)
val doubled3 = numbers.map { it * 2 }// 过滤
val filtered = numbers.filter { it % 2 == 0 }// 捕获值
fun makeIncrementer(incrementAmount: Int): () -> Int {var total = 0return {total += incrementAmounttotal}
}val incrementByTwo = makeIncrementer(2)
println(incrementByTwo())  // 2
println(incrementByTwo())  // 4

扩展与Extension

Swift Extension

// 扩展基本类型
extension String {var isEmail: Bool {return self.contains("@") && self.contains(".")}func reversed() -> String {return String(self.reversed())}
}// 扩展自定义类型
extension Person {func greet() -> String {return "Hello, I'm \(name)"}var isAdult: Bool {return age >= 18}
}// 使用扩展
let email = "test@example.com"
print(email.isEmail)  // true
print("Swift".reversed())  // tfiwSlet person = Person(name: "张三", age: 20)
print(person.greet())
print(person.isAdult)

Kotlin Extension

// 扩展基本类型
val String.isEmail: Booleanget() = this.contains("@") && this.contains(".")fun String.reversed(): String {return this.reversed()
}// 扩展自定义类型
fun Person.greet(): String {return "Hello, I'm $name"
}val Person.isAdult: Booleanget() = age >= 18// 使用扩展
val email = "test@example.com"
println(email.isEmail)  // true
println("Kotlin".reversed())  // niltoKval person = Person("张三", 20)
println(person.greet())
println(person.isAdult)

错误处理

Swift 错误处理

// 定义错误类型
enum ValidationError: Error {case emptyNamecase invalidAgecase invalidEmail
}// 可能抛出错误的函数
func validateUser(name: String, age: Int, email: String) throws -> Bool {if name.isEmpty {throw ValidationError.emptyName}if age < 0 || age > 150 {throw ValidationError.invalidAge}if !email.contains("@") {throw ValidationError.invalidEmail}return true
}// 错误处理
do {try validateUser(name: "张三", age: 25, email: "zhang@example.com")print("用户验证成功")
} catch ValidationError.emptyName {print("姓名不能为空")
} catch ValidationError.invalidAge {print("年龄无效")
} catch ValidationError.invalidEmail {print("邮箱格式无效")
} catch {print("未知错误: \(error)")
}// try? 和 try!
let result1 = try? validateUser(name: "李四", age: 30, email: "li@example.com")
let result2 = try! validateUser(name: "王五", age: 28, email: "wang@example.com")

Kotlin 异常处理

// 自定义异常
class ValidationException(message: String) : Exception(message)// 可能抛出异常的函数
fun validateUser(name: String, age: Int, email: String): Boolean {if (name.isEmpty()) {throw ValidationException("姓名不能为空")}if (age < 0 || age > 150) {throw ValidationException("年龄无效")}if (!email.contains("@")) {throw ValidationException("邮箱格式无效")}return true
}// 异常处理
try {validateUser("张三", 25, "zhang@example.com")println("用户验证成功")
} catch (e: ValidationException) {println("验证错误: ${e.message}")
} catch (e: Exception) {println("未知错误: ${e.message}")
}// runCatching (类似 try?)
val result = runCatching {validateUser("李四", 30, "li@example.com")
}.getOrNull()

内存管理

Swift ARC (自动引用计数)

class Person {let name: Stringvar apartment: Apartment?init(name: String) {self.name = name}deinit {print("\(name) 被释放")}
}class Apartment {let unit: Stringweak var tenant: Person?  // 弱引用避免循环引用init(unit: String) {self.unit = unit}deinit {print("公寓 \(unit) 被释放")}
}// 使用
var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")john?.apartment = unit4A
unit4A?.tenant = john// 释放引用 - Swift ARC 需要手动打破循环引用
// 如果不手动置 nil,即使使用了 weak 引用,外部强引用仍然存在
john = nil    // 释放 Person 实例的强引用
unit4A = nil  // 释放 Apartment 实例的强引用

Kotlin GC (垃圾回收)

class Person(val name: String) {var apartment: Apartment? = nullprotected fun finalize() {println("$name 被回收")}
}class Apartment(val unit: String) {var tenant: Person? = null  // Kotlin 的 GC 会处理循环引用protected fun finalize() {println("公寓 $unit 被回收")}
}// 使用
var john: Person? = Person("John")
var unit4A: Apartment? = Apartment("4A")john?.apartment = unit4A
unit4A?.tenant = john// 释放引用 - Kotlin GC 可以自动处理循环引用
// 即使不手动置 null,GC 也能检测并回收循环引用的对象
john = null  // 可选操作,GC 会自动处理
unit4A = null  // 可选操作,GC 会自动处理

Swift ARC vs Kotlin GC 对比

回答你的问题:你说得对!Kotlin 确实不需要手动置 null,而 Swift 在某些情况下需要。

内存管理机制对比
特性Swift ARCKotlin GC
管理方式自动引用计数垃圾回收器
循环引用处理需要 weak/unowned 引用自动检测和处理
手动置 nil有时需要通常不需要
性能特点确定性释放,低延迟可能有 GC 暂停
内存泄漏风险循环引用导致泄漏很少发生
具体差异说明

Swift ARC 的限制

// 即使使用了 weak 引用,外部强引用仍需手动释放
var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")john?.apartment = unit4A
unit4A?.tenant = john  // weak 引用// 必须手动置 nil,否则 john 和 unit4A 不会被释放
john = nil    // 必需!
unit4A = nil  // 必需!

Kotlin GC 的优势

// GC 可以自动检测循环引用
var john: Person? = Person("John")
var unit4A: Apartment? = Apartment("4A")john?.apartment = unit4A
unit4A?.tenant = john  // 普通引用// 不需要手动置 null,GC 会自动处理
// john = null  // 可选
// unit4A = null  // 可选// 当这些变量超出作用域时,GC 会自动回收
核心要点
  • Swift:ARC 基于引用计数,无法自动处理循环引用,需要开发者使用 weak/unowned 和手动置 nil
  • Kotlin:GC 可以检测并自动回收循环引用的对象,开发者无需特殊处理
  • 最佳实践:Swift 中养成手动置 nil 的习惯,Kotlin 中可以依赖 GC 自动管理

这就是为什么 Swift 开发者需要更加注意内存管理,而 Kotlin/Java 开发者相对轻松一些。


实战练习

练习1:创建一个简单的学生管理系统

Swift 版本
struct Student {let id: Stringvar name: Stringvar age: Intvar scores: [String: Double]  // 科目: 分数var averageScore: Double {guard !scores.isEmpty else { return 0.0 }return scores.values.reduce(0, +) / Double(scores.count)}mutating func addScore(subject: String, score: Double) {scores[subject] = score}
}class StudentManager {private var students: [String: Student] = [:]func addStudent(_ student: Student) {students[student.id] = student}func getStudent(id: String) -> Student? {return students[id]}func getAllStudents() -> [Student] {return Array(students.values)}func getTopStudents(count: Int) -> [Student] {return getAllStudents().sorted { $0.averageScore > $1.averageScore }.prefix(count).map { $0 }}
}// 使用示例
let manager = StudentManager()var student1 = Student(id: "001", name: "张三", age: 20, scores: [:])
student1.addScore(subject: "数学", score: 95.0)
student1.addScore(subject: "英语", score: 87.0)manager.addStudent(student1)if let student = manager.getStudent(id: "001") {print("学生: \(student.name), 平均分: \(student.averageScore)")
}
Kotlin 版本
data class Student(val id: String,var name: String,var age: Int,private val scores: MutableMap<String, Double> = mutableMapOf()
) {val averageScore: Doubleget() = if (scores.isEmpty()) 0.0 else scores.values.average()fun addScore(subject: String, score: Double) {scores[subject] = score}fun getScores(): Map<String, Double> = scores.toMap()
}class StudentManager {private val students = mutableMapOf<String, Student>()fun addStudent(student: Student) {students[student.id] = student}fun getStudent(id: String): Student? {return students[id]}fun getAllStudents(): List<Student> {return students.values.toList()}fun getTopStudents(count: Int): List<Student> {return getAllStudents().sortedByDescending { it.averageScore }.take(count)}
}// 使用示例
val manager = StudentManager()val student1 = Student("001", "张三", 20)
student1.addScore("数学", 95.0)
student1.addScore("英语", 87.0)manager.addStudent(student1)manager.getStudent("001")?.let { student ->println("学生: ${student.name}, 平均分: ${student.averageScore}")
}

练习2:网络请求封装

Swift 版本
import Foundationenum NetworkError: Error {case invalidURLcase noDatacase decodingError
}class NetworkManager {static let shared = NetworkManager()private init() {}func request<T: Codable>(url: String,type: T.Type,completion: @escaping (Result<T, NetworkError>) -> Void) {// guard 语句:提前退出模式,确保条件满足才继续执行// 类似 Kotlin 的 require() 或 early return 模式guard let url = URL(string: url) else {completion(.failure(.invalidURL))return  // 条件不满足时提前退出}URLSession.shared.dataTask(with: url) { data, response, error inguard let data = data else {completion(.failure(.noData))return}do {let result = try JSONDecoder().decode(type, from: data)completion(.success(result))} catch {completion(.failure(.decodingError))}}.resume()}
}// 使用示例
struct User: Codable {let id: Intlet name: Stringlet email: String
}NetworkManager.shared.request(url: "https://api.example.com/users/1",type: User.self
) { result inswitch result {case .success(let user):print("用户: \(user.name)")case .failure(let error):print("错误: \(error)")}
}
Kotlin 版本
import kotlinx.coroutines.*
import kotlinx.serialization.*
import kotlinx.serialization.json.*sealed class NetworkResult<T> {data class Success<T>(val data: T) : NetworkResult<T>()data class Error<T>(val message: String) : NetworkResult<T>()
}class NetworkManager {companion object {val instance = NetworkManager()}private val json = Json { ignoreUnknownKeys = true }suspend inline fun <reified T> request(url: String): NetworkResult<T> {return withContext(Dispatchers.IO) {try {// 这里应该使用实际的 HTTP 客户端,如 OkHttpval response = ""  // 模拟响应val result = json.decodeFromString<T>(response)NetworkResult.Success(result)} catch (e: Exception) {NetworkResult.Error(e.message ?: "Unknown error")}}}
}// 使用示例
@Serializable
data class User(val id: Int,val name: String,val email: String
)// 在协程中使用
GlobalScope.launch {when (val result = NetworkManager.instance.request<User>("https://api.example.com/users/1")) {is NetworkResult.Success -> {println("用户: ${result.data.name}")}is NetworkResult.Error -> {println("错误: ${result.message}")}}
}

Guard 语句详解

什么是 Guard 语句

guard 是 Swift 中的一个关键字,用于提前退出模式(Early Exit Pattern)。它确保某个条件必须为真,否则就提前退出当前作用域。

基本语法

guard 条件 else {// 条件不满足时执行的代码return  // 必须有退出语句
}
// 条件满足时继续执行的代码

Guard vs If Let 对比

// 使用 if let(嵌套结构)
func processUser(name: String?) {if let userName = name {if userName.count > 0 {if userName != "admin" {print("处理用户: \(userName)")// 更多逻辑...} else {print("管理员用户")return}} else {print("用户名为空")return}} else {print("用户名为 nil")return}
}// 使用 guard(扁平结构)
func processUserWithGuard(name: String?) {guard let userName = name else {print("用户名为 nil")return}guard userName.count > 0 else {print("用户名为空")return}guard userName != "admin" else {print("管理员用户")return}print("处理用户: \(userName)")// 更多逻辑...
}

Guard 的优势

  1. 减少嵌套:避免金字塔式的 if-else 嵌套
  2. 提高可读性:主要逻辑更清晰
  3. 强制处理:必须在 else 块中处理异常情况
  4. 作用域扩展:guard let 绑定的变量在后续代码中可用

与 Kotlin 的对比

特性Swift GuardKotlin 等价写法
提前退出guard condition else { return }if (!condition) return
空值检查guard let value = optional else { return }val value = optional ?: return
条件验证guard user.isValid else { return }require(user.isValid) { "Invalid user" }
多条件检查多个 guard 语句takeIf { } 或多个 require
Kotlin 对应写法示例
// Swift guard 对应的 Kotlin 写法
fun processUser(name: String?) {// Swift: guard let userName = name else { return }val userName = name ?: return// Swift: guard userName.isNotEmpty() else { return }if (userName.isEmpty()) return// Swift: guard userName != "admin" else { return }require(userName != "admin") { "Admin user not allowed" }println("处理用户: $userName")
}// 或者使用 takeIf
fun processUserWithTakeIf(name: String?) {name?.takeIf { it.isNotEmpty() }?.takeIf { it != "admin" }?.let { userName ->println("处理用户: $userName")}
}

核心要点

  1. 必须退出:guard 的 else 块必须包含 returnbreakcontinuethrow 等退出语句
  2. 扁平化代码:避免深层嵌套,让主要逻辑更突出
  3. 变量作用域:guard let 绑定的变量在整个函数剩余部分可用
  4. 错误处理:适合用于参数验证和前置条件检查
  5. Kotlin 替代:主要使用 ?: 操作符、require()takeIf() 等实现类似效果

总结

学习建议

  1. 从相似点开始:Swift 和 Kotlin 有很多相似的概念,可以快速上手
  2. 重点关注差异:特别注意可选类型、内存管理、语法细节的不同
  3. 多写代码:理论学习后要多实践,加深理解
  4. 利用工具:使用 Xcode 的代码补全和错误提示
  5. 阅读官方文档:Apple 的 Swift 文档非常详细

下一步学习方向

  1. iOS 框架学习:UIKit、SwiftUI、Core Data 等
  2. 架构模式:MVC、MVVM、VIPER 等
  3. 网络编程:URLSession、Alamofire 等
  4. 数据持久化:Core Data、SQLite、UserDefaults
  5. 测试:XCTest、UI Testing
  6. 性能优化:Instruments、内存管理

常用资源

  • Swift 官方文档
  • Apple Developer Documentation
  • Swift Playgrounds
  • Hacking with Swift
  • Ray Wenderlich

本指南持续更新中,欢迎反馈和建议!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95893.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95893.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/95893.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式C语言笔记十七——构造数据类型

一.结构体&#xff1a;1.类型定义&#xff1a;struct 结构体名 {数据类型1 成员变量1;数据类型2 成员变量2;数据类型3 成员变量3;... };struct student {char name[32];char sex;int age;int score; };2.结构体变量定义&#xff1a;存储类型 数据类型 变量名;3.结构体元素初始化…

深入实践G1垃圾收集器调优:Java应用性能优化实战指南

深入实践G1垃圾收集器调优&#xff1a;Java应用性能优化实战指南 一、技术背景与应用场景 随着微服务和海量并发请求的普及&#xff0c;Java应用在生产环境中对低延迟和高吞吐的需求日益显著。传统的CMS和Parallel GC 在大内存场景下常出现Full GC 停顿时间长、吞吐下降等问题…

【JobScheduler】Android 后台任务调度的核心组件指南

JobScheduler 是 Android 平台上原生支持在直接启动模式&#xff08;Direct Boot Mode&#xff09;下执行任务的调度器。 相比 WorkManager 需要复杂的配置才能勉强支持直接启动&#xff0c;JobScheduler 在这方面有着天生的优势和明确的 API 支持。如果你面临的硬性要求是必须…

c# 调用basler 相机

目录 一联合halcon&#xff1a; 二 c# 原生 一联合halcon&#xff1a; 环境配置 下载安装pylon软件 下载安装halcon 创建 winform项目 test_basler 添加引用 打开pylon可以连接相机 可以看到我的相机id为23970642 &#xff08; c#联合halcon的基础教程&#xff08;案例…

《2025年AI产业发展十大趋势报告》四十六

《2025年AI产业发展十大趋势报告》四十六随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;作为引领新一轮科技革命和产业变革的战略性技术&#xff0c;正逐步渗透到各个行业和领域&#xff0c;成为推动经济社会发展的重要引擎。2023年&#xff0c;生成式AI的…

c++ 杂记

1. 为什么返回*this?2. 3. 友元函数的使用&#xff1a;需要头文件中类内外声明&#xff0c;cpp文件中实现定义哦// Sales_data.h #ifndef SALES_DATA_H #define SALES_DATA_H#include <string>class Sales_data {std::string bookNo;int units_sold 0;double revenue …

PDF文件基础-计算机字体

计算机字体的原理包含了字符编码、字形渲染和字体文件存储三个关键技术。 字符编码负责将每个字符映射到一个唯一的数字码&#xff1b;字形渲染则将这些数字码转换成屏幕或纸张上可识别的图形&#xff1b;字体文件存储则包含了字符的编码、图形描述信息以及字体的其他属性&…

华为IP(9)

OSPF的基本配置OSPF路由计算前言&#xff1a;1)同一区域内的OSPF路由器拥有完全一致的LSDB&#xff0c;在区域内部&#xff0c;OSPF采用SPF算法完成路由计算。2&#xff09;随着网络规模不断扩大&#xff0c;路由器为了完成路由计算所消耗的内存、CPU资源也越来越多。通过区域划…

java.nio.file.InvalidPathException异常

一.问题概述 本人在ubuntu22.04的操作系统上&#xff0c;运行java程序时创建一个文件时&#xff0c;由于文件名称中包含了中文&#xff0c;所以导致了程序抛出了java.nio.file.InvalidPathException的异常。 java.nio.file.InvalidPathException: Malformed input or input co…

Next系统总结学习(一)

下面我按题号逐条 详细 解释并给出示例与最佳实践。为便于阅读&#xff0c;我会同时给出关键代码片段&#xff08;伪代码/实用例子&#xff09;&#xff0c;并指出常见坑与解决方案。 1. 你是如何理解服务端渲染&#xff08;SSR&#xff09;的&#xff1f;它的核心工作流程是怎…

房屋安全鉴定需要什么条件

房屋安全鉴定需要什么条件&#xff1a;专业流程与必备要素解析房屋安全鉴定是保障建筑使用安全的重要环节&#xff0c;它通过对建筑结构、材料性能及使用状况的全面评估&#xff0c;为房屋的安全使用、改造或维护提供科学依据。随着城市建筑老化及自然灾害频发&#xff0c;房屋…

现代C++:现代C++?

C语言正在走向完美&#xff0c;所以&#xff0c;C语言值得学习&#xff08;甚至研究&#xff09;&#xff0c;这些知识可以成为一切编程的基础。然而在实践中&#xff0c;不必全面的使用C语言的各种特性&#xff0c;而应根据工程项目的实际情况&#xff0c;适当取舍&#xff08…

【C++】哈希表实现

1. 哈希概念 哈希(hash)又称散列&#xff0c;是⼀种组织数据的方式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希 函数把关键字Key跟存储位置建立一个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进行快速查找 1.1 直接定址法…

ai 玩游戏 llm玩街霸 大模型玩街霸 (3)

1. 开源代码地址&#xff1a; https://github.com/OpenGenerativeAI/llm-colosseum 2. 架构&#xff1a; 3. 图片&#xff1a; 4. 感觉还是下面的步骤&#xff1a; a. 实时理解游戏当前环境&#xff0c;英雄角色&#xff0c;英雄状态 b. 根据当前状态感知&#xff0c;生成英雄…

2025年渗透测试面试题总结-59(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、SQL注入全解 二、XSS与文件漏洞 三、服务端漏洞专题 四、职业经验与能力评估 1、注入攻击原理是什么…

GPT系列--类GPT2源码剖析

无需多言&#xff0c;大家应该都用过了&#xff0c;如今都更新到GPT-5了。1. GPT-1回到2018年的NLP&#xff0c;神仙打架&#xff0c;BERT与GPT不分先后。GPT是“Generative Pre-Training”的简称&#xff0c;生成式的预训练。BERT和GPT肯定是GPT难训练&#xff0c;引用量也是B…

这是一款没有任何限制的免费远程手机控制手机的软件

这是一款没有任何限制的免费远程手机控制手机的软件支持安卓和苹果1.安装1.1被控制端安装airdroid1.2控制端air mirror2.登录账号控制端和被控制端登录同一个账号3.控制打开控制端软件选择要控制的机器直接点“远程控制“

Observability:更智能的告警来了:更快的分诊、更清晰的分组和可操作的指导

作者&#xff1a;来自 Elastic Drew Post 探索 Elastic Stack 告警的最新增强功能&#xff0c;包括改进的相关告警分组、将仪表盘链接到告警规则&#xff0c;以及将调查指南嵌入到告警中。 在 9.1 版本中&#xff0c;我们对告警进行了重大升级&#xff0c;帮助 SRE 和运维人员更…

数智之光燃盛景 共同富裕创丰饶

8月29日&#xff0c;2025数博会“一带一路”国际大数据产业发展暨数智赋能新时代、共同富裕向未来的会议在贵阳国际生态会议中心隆重举行。作为全球大数据领域的重要盛会&#xff0c;此次活动吸引了来自联合国机构、国际组织、科研院所、知名企业等社会各界的百余位代表&#x…

【网络编程】recv函数的本质是什么?

一、为什么说recv函数的本质是 “copy”&#xff1f; recv是用于从网络连接&#xff08;或其他 IO 对象&#xff09;接收数据的函数&#xff0c;它的核心动作不是 “从网络上拉取数据”&#xff0c;而是 “把已经到达内核缓冲区的数据复制到用户程序的缓冲区”。 具体流程拆解&…