swift-12-Error处理、关联类型、assert、泛型_

news2025/5/9 16:13:06

一、错误类型

开发过程常见的错误
语法错误(编译报错)
逻辑错误
运行时错误(可能会导致闪退,一般也叫做异常)

2.1 通过结构体

第一步
struct MyError : Errort {
var msg: String
}
第二步
func divide(_ num1: Int, - num2: Int) throws -> Int ‹
if num2 == 0 {
第三步
throw MyError(msg:"0不能作为除数")
}
return numi / num2
}
divide (1,0)

2.2 枚举定义错误信息

Swift中可以通过Error协议自定义运行时的错误信息

enum SomeError : Error {
case illegalArg(String)
case outOfBounds(Int, Int) case outOfMemory
}

 函数内部通过throw抛出自定义Error ,可能会抛出Error的函数必须加上throws声明

func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw SomeError.illegalArg("0不能作为除数")
}
return num1 / num2
}

需要使用try调用可能会抛出Error的函数

var result = try divide(20, 10)

2.3 处理错误信息do-catch

可以使用do-catch捕捉Error

func test {
print ("1")
do {
print ("2")
print(try divide (200, 0))
//一旦这句回抛出异常,do作用越后边的代码都不会执行,也就是后边的都不会执行
print ("3")
print ("3")
print ("3")
print ("3" )
print ("3")
¿ catch let SomeError.illegalArg(msg) ‹
print ("参数异常:",msg)
} catch let SomeError.outOfBounds(size, index) {
print("下标越界:","size=\(size)",
, "index=\(index)")
} catch SomeError.outOfMemory 1
print("内存溢出")
¿ catch {
print("其他错误")
print ("4")
}



test()
// 1
// 2
// 参数异常 : 0不能作为除数 // 4

这种方式和上面的那种方式一样,先拿到所有的error 再case

do {
try divide(20, 0)
} catch let error {
switch error {
case let SomeError.illegalArg(msg):
print("参数错误: ", msg)
 default:
print("其他错误")
}
}

抛出Error后,try下一句直到作用域结束的代码都将停止运行

2.4 处理Error

处理Error的2种方式
①  通过do-catch捕捉Error
②  不捕捉Error ,在当前函数增加throws声明,Error将自动抛给上层函数
 如果最顶层函数( main函数)依然没有捕捉Error ,那么程序将终止

这里抛给调用者处理
func test() throws {
print("1")
print(try divide(20, 0))
print("2")
}
try test()
// 1
// Fatal error: Error raised at top level

处理方式一
do {
print(try divide(20, 0))
} catch is SomeError {
print("SomeError")
}


处理方式二
func test() throws {
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
} catch let error as SomeError {
print(error)
}
print("4")
}
try test()
// 1
// 2
// illegalArg("0不能作为除数") // 4

2.5 注意点

func testo(){
test1 ()
}

func test1() {
test2 ()
}
func test2() {
do {
print(try divide (200, 0)) 2 
如果这里只写一个catch的情况还是回报错,告诉你没有处理所有的错误信息
} catch is SomeError {
print ("This is SomeError")
}

解决办法
func test2) {
do {
print(try divide (200, 0))
} catch is SomeError {
print ("This is SomeError")
} catch {
}
}

或者往上抛
func test0()throws {
try test1()
}
}
func test1() throws {
try test2()
}

func test2() throws {
do {
print(try divide (200,0))
}catch is SomeError {
print ("This is SomeError")
  }
}

二、try?、 try!

 可以使用try?、 try!调用可能会抛出Error的函数,这样就不用去处理Error

func test() {
print("1")
var result1 = try? divide(20, 10) // Optional(2), Int?
var result2 = try? divide(20, 0) // nil
var result3 = try! divide(20, 10) // 2, Int
print("2")
}
test()

a、 b是等价的
var a = try? divide(20, 0) var b: Int?
do {
b = try divide(20, 0)
} catch { b = nil }

三、rethrows

rethrows表明:函数本身不会抛出错误,但调用闭包参数抛出错误,那么它会将错误向上抛

func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
print(try fn(num1, num2))
}
// Fatal error: Error raised at top level
try exec(divide, 20, 0)

四、defer

defer语句:用来定义以任何方式(抛错误、 return等)离开代码块前必须要执行的代码

defer语句将延迟至当前作用域结束之前执行

func open(_ filename: String) -> Int {
print("open")
return 0
}
func close(_ file: Int) {
print("close")
}



func processFile(_ filename: String) throws {
let file = open(filename)
defer {
close(file)
}
// 使用file // ....
try divide(20, 0)

// close将会在这里调用
}
try processFile("test.txt")
// open
// close
// Fatal error: Error raised at top level



defer语句的执行顺序与定义顺序相反

func fn1() { print("fn1") }
func fn2() { print("fn2") }
func test() {
defer { fn1() }
defer { fn2() }
}
test()
// fn2
// fn1

二、泛型(Generics 

2.1 范型函数的定义和普通函数的定义的区别

swapValues<T> 这里要加<T> 表示范型函数

型可以将类型参数化,提高代码复用率,减少代码量

func swapValues<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}


var i1 = 10 var i2 = 20
swapValues(&i1, &i2)

var d1 = 10.0 var d2 = 20.0
swapValues(&d1, &d2)

struct Date {
var year = 0, month = 0, day = 0
}
var dd1 = Date(year: 2011, month: 9, day: 10)
var dd2 = Date(year: 2012, month: 10, day: 11)
swapValues(&dd1, &dd2)

泛型函数赋值给变量

func test<T1, T2>(_ t1: T1, _ t2: T2) {}
var fn: (Int, Double) -> () = test

2.2 泛型类型

2.2.1 泛型类型类

class Stack<E> {
var elements = [E]()
func push(_ element: E) { elements.append(element) }
func pop() -> E { elements.removeLast() }
func top() -> E { elements.last! }
func size() -> Int { elements.count }
}


var stack = Stack<Int>()
stack.push(11)
stack.push(22)
stack.push(33)
print(stack.top()) // 33
print(stack.pop()) // 33
print(stack.pop()) // 22
print(stack.pop()) // 11
print(stack.size()) // 0

2.2.2 泛型类型 继承

class SubStack<E> : Stack<E> {}

2.2.3 泛型类型结构体

struct Stack<E> {
var elements = [E]()
mutating func push(_ element: E) { elements.append(element) }
mutating func pop() -> E { elements.removeLast() }
func top() -> E { elements.last! }
func size() -> Int { elements.count }
}

2.2.4 泛型类型枚举

enum Score<T> {
case point(T)
case grade(String)
}
let score0 = Score<Int>.point(100)
let score1 = Score.point(99)
let score2 = Score.point(99.5)
let score3 = Score<Int>.grade("A")

三、关联类型(Associated Type) 协议范型的表示方法

关联类型的作用:给协议中用到的类型定义一个占位名称

协议中可以拥有多个关联类型

protocol Stackable {
associatedtype Element // 关联类型
mutating func push(_ element: Element)
mutating func pop() -> Element
func top() -> Element
func size() -> Int
}



class StringStack : Stackable {
// 给关联类型设定真实类型
// typealias Element = String
var elements = [String]()
func push(_ element: String) { elements.append(element) }
func pop() -> String { elements.removeLast() }
func top() -> String { elements.last! }
func size() -> Int { elements.count }
}
var ss = StringStack()
ss.push("Jack")
ss.push("Rose")


class Stack<E> : Stackable {
// typealias Element = E
var elements = [E]()
func push(_ element: E) {
elements.append(element)
}
func pop() -> E { elements.removeLast() }
func top() -> E { elements.last! }
func size() -> Int { elements.count }
}

四、类型约束 1.50 

T : Person & Runnable 约束T 遵守Runnable并且是Person类型

protocol Runnable { }
class Person { }
func swapValues<T : Person & Runnable>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
protocol Stackable {
associatedtype Element : Equatable
}
class Stack<E : Equatable> : Stackable 1
typealias I
Element = E
}
protocol Stackable {
associatedtype Element: Equatable
}
class Stack<E : Equatable> : Stackable { typealias Element = E }
func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool
where S1.Element == S2.Element, S1.Element : Hashable {
return false
}


var stack1 = Stack<Int>()
var stack2 = Stack<String>()
// error: requires the types 'Int' and 'String' be equivalent
equal(stack1, stack2)

四、协议类型的注意点 2.00

protocol Runnable {}
class Person : Runnable {}
class Car : Runnable {}

func get(_ type: Int) -> Runnable {
if type == 0 {
return Person()
}
return Car()
}

var r1 = get(0)
var r2 = get(1)

如果协议中有associatedtype

protocol Runnable {
associatedtype Speed
var speed: Speed { get }
}
class Person : Runnable {
var speed: Double { 0.0 }
}
class Car : Runnable {
var speed: Int { 0 }
}

4.1 泛型解决

 解决方案① :使用泛型

func get<T : Runnable>(_ type: Int) -> T {
if type == 0 {
return Person() as ! T
}
return Car() as ! T
}
var r1: Person = get(0)
var r2: Car = get(1)

4.2、不透明类型(Opaque Type

func get(_ type: Int) -> some Runnable { Car() }
var r1 = get(0)
var r2 = get(1)
some限制只能返回一种类型

五、some

some 解决Runnable带有关联类型的报错的问题

some除了用在返回值类型上,一般还可以用在属性类型上

protocol Runnable { associatedtype Speed }
class Dog : Runnable { typealias Speed = Double }
class Person {
var pet: some Runnable {
return Dog()
}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nacos安装及数据持久化

1.Nacos安装及数据持久化 1.1下载nacos 下载地址&#xff1a;https://nacos.io/download/nacos-server/ 不用安装&#xff0c;直接解压缩即可。 1.2配置文件增加jdk环境和修改单机启动standalone 找到bin目录下的startup.cmd文件&#xff0c;添加以下语句(jdk路径根据自己…

FPGA_YOLO(四)用HLS实现循环展开以及存储模块

Vivado HLS&#xff08;High-Level Synthesis&#xff0c;高层次综合&#xff09;是赛灵思&#xff08;Xilinx&#xff09;在其 Vivado 设计套件 中提供的一款工具&#xff0c;用于将 高级编程语言&#xff08;如 C、C、SystemC&#xff09; 直接转换为 硬件描述语言&#xff0…

ASP.NET MVC 实现增删改查(CRUD)操作的完整示例

提供一个完整的 ASP.NET MVC 实现增删改查&#xff08;CRUD&#xff09;操作的示例。该示例使用 SQL Server 数据库&#xff0c;以一个简单的 Product 实体为例。 步骤 1&#xff1a;创建 ASP.NET MVC 项目 首先&#xff0c;在 Visual Studio 中创建一个新的 ASP.NET MVC 项目…

MCP理解笔记及deepseek使用MCP案例介绍

文章目录 一、MCP介绍&#xff08;1&#xff09;使用MCP与之前的AI比较&#xff08;2&#xff09;原理&#xff08;3&#xff09;优点 二、deepseek使用MCP使用案例介绍 一、MCP介绍 全称 模型上下文协议 来源 由Claude母公司Anthropic于24年底开源发布 简介 AI大模型的标准化…

# 手写数字识别:使用PyTorch构建MNIST分类器

手写数字识别&#xff1a;使用PyTorch构建MNIST分类器 在这篇文章中&#xff0c;我将引导你通过使用PyTorch框架构建一个简单的神经网络模型&#xff0c;用于识别MNIST数据集中的手写数字。MNIST数据集是一个经典的机器学习数据集&#xff0c;包含了60,000张训练图像和10,000张…

LeetCode:DFS综合练习

简单 1863. 找出所有子集的异或总和再求和 一个数组的 异或总和 定义为数组中所有元素按位 XOR 的结果&#xff1b;如果数组为 空 &#xff0c;则异或总和为 0 。 例如&#xff0c;数组 [2,5,6] 的 异或总和 为 2 XOR 5 XOR 6 1 。 给你一个数组 nums &#xff0c;请你求出 n…

Perf学习

重要的能解决的问题是这些&#xff1a; perf_events is an event-oriented observability tool, which can help you solve advanced performance and troubleshooting functions. Questions that can be answered include: Why is the kernel on-CPU so much? What code-pa…

齐次坐标变换+Unity矩阵变换

矩阵变换 变换&#xff08;transform)&#xff1a;指的是我们把一些数据&#xff0c;如点&#xff0c;方向向量甚至是颜色&#xff0c;通过某种方式&#xff08;矩阵运算&#xff09;&#xff0c;进行转换的过程。 变换类型 线性变换&#xff1a;保留矢量加和标量乘的计算 f(x)…

Pandas取代Excel?

有人在知乎上提问&#xff1a;为什么大公司不用pandas取代excel&#xff1f; 而且列出了几个理由&#xff1a;Pandas功能比Excel强大&#xff0c;运行速度更快&#xff0c;Excel除了简单和可视化界面外&#xff0c;没有其他更多的优势。 有个可怕的现实是&#xff0c;对比Exce…

启动vite项目报Unexpected “\x88“ in JSON

启动vite项目报Unexpected “\x88” in JSON 通常是文件被防火墙加密需要寻找运维解决 重启重装npm install

HTTP测试智能化升级:动态变量管理实战与效能跃迁

在Web应用、API接口测试等领域&#xff0c;测试场景的动态性和复杂性对测试数据的灵活管理提出了极高要求。传统的静态测试数据难以满足多用户并发、参数化请求及响应内容验证等需求。例如&#xff0c;在电商系统性能测试中&#xff0c;若无法动态生成用户ID、订单号或实时提取…

关于一对多关系(即E-R图中1:n)中的界面展示优化和数据库设计

前言 一对多&#xff0c;是常见的数据库关系。在界面设计时&#xff0c;有时为了方便&#xff0c;就展示成逗号分割的字符串。例如&#xff1a;学生和爱好的界面。 存储 如果是简单存储&#xff0c;建立数据库&#xff1a;爱好&#xff0c;课程&#xff0c;存在一张表中。 但…

JVM笔记【一】java和Tomcat类加载机制

JVM笔记一java和Tomcat类加载机制 java和Tomcat类加载机制 Java类加载 * loadClass加载步骤类加载机制类加载器初始化过程双亲委派机制全盘负责委托机制类关系图自定义类加载器打破双亲委派机制 Tomcat类加载器 * 为了解决以上问题&#xff0c;tomcat是如何实现类加载机制的…

React 组件类型详解:类组件 vs. 函数组件

React 是一个用于构建用户界面的 JavaScript 库&#xff0c;其核心思想是组件化开发。React 组件可以分为类组件&#xff08;Class Components&#xff09;和函数组件&#xff08;Function Components&#xff09;&#xff0c;它们在设计理念、使用方式和适用场景上有所不同。随…

GPT-SoVITS 使用指南

一、简介 TTS&#xff08;Text-to-Speech&#xff0c;文本转语音&#xff09;&#xff1a;是一种将文字转换为自然语音的技术&#xff0c;通过算法生成人类可听的语音输出&#xff0c;广泛应用于语音助手、无障碍服务、导航系统等场景。类似的还有SVC&#xff08;歌声转换&…

美信监控易:数据采集与整合的卓越之选

在当今复杂多变的运维环境中&#xff0c;一款具备强大数据采集与整合能力的运维管理软件对于企业的稳定运行和高效决策至关重要。美信监控易正是这样一款在数据采集与整合方面展现出显著优势的软件&#xff0c;以下是它的一些关键技术优势&#xff0c;值得每一个运维团队深入了…

End-to-End从混沌到秩序:基于LLM的Pipeline将非结构化数据转化为知识图谱

摘要:本文介绍了一种将非结构化数据转换为知识图谱的端到端方法。通过使用大型语言模型(LLM)和一系列数据处理技术,我们能够从原始文本中自动提取结构化的知识。这一过程包括文本分块、LLM 提示设计、三元组提取、归一化与去重,最终利用 NetworkX 和 ipycytoscape 构建并可…

MySql 三大日志(redolog、undolog、binlog)详解

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/aa730ab3f84049638f6c9a785e6e51e9.png 1. redo log&#xff1a;“你他妈别丢数据啊&#xff01;” 干啥的&#xff1f; 这货是InnoDB的“紧急备忘录”。比如你改了一条数据&#xff0c;MySQL怕自己突然断电嗝屁了&am…

HTTP:九.WEB机器人

概念 Web机器人是能够在无需人类干预的情况下自动进行一系列Web事务处理的软件程序。人们根据这些机器人探查web站点的方式,形象的给它们取了一个饱含特色的名字,比如“爬虫”、“蜘蛛”、“蠕虫”以及“机器人”等!爬虫概述 网络爬虫(英语:web crawler),也叫网络蜘蛛(…

2025妈妈杯数学建模C题完整分析论文(共36页)(含模型建立、可运行代码、数据)

2025 年第十五届 MathorCup 数学建模C题完整分析论文 目录 摘 要 一、问题分析 二、问题重述 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1代码&#xff08;仅供参考&#xff09; 4.1.4问题1求解结果&#xff08;仅…