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

一、错误类型

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

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 再casedo {
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)如果协议中有associatedtypeprotocol 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.mzph.cn/bicheng/77553.shtml

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

相关文章

实验扩充 LED显示4*4键位值

代码功能概述 键盘扫描&#xff1a; 使用 KeyPort&#xff08;定义为 P1&#xff09;作为键盘输入端口。扫描 4x4 矩阵键盘&#xff0c;检测按键并返回按键编号&#xff08;0~15&#xff09;。 数码管显示&#xff1a; 根据按键编号&#xff0c;从 SegCode 数组中获取对应数码…

从零开始搭建CLIP模型实现基于文本的图像检索

目录 CLIP原理简介代码实现参考链接 CLIP原理简介 论文链接&#xff0c;源码链接 CLIP模型由OpenAI在2021年提出&#xff0c;利用双Decoder&#xff08;Dual Encoder&#xff09;的架构来学习图像和文本之间的对应关系&#xff0c;是多模态大模型的开创之作&#xff0c;为后续许…

熊海cms代码审计

目录 sql注入 1. admin/files/login.php 2. admin/files/columnlist.php 3. admin/files/editcolumn.php 4. admin/files/editlink.php 5. admin/files/editsoft.php 6. admin/files/editwz.php 7. admin/files/linklist.php 8. files/software.php 9. files…

[Java微服务组件]注册中心P3-Nacos中的设计模式1-观察者模式

在P1-简单注册中心实现和P2-Nacos解析中&#xff0c;我们分别实现了简单的注册中心并总结了Nacos的一些设计。 本篇继续看Nacos源码&#xff0c;了解一下Nacos中的设计模式。 目录 Nacos 观察者模式 Observer Pattern观察者模式总结 Nacos 观察者模式 Observer Pattern 模式定…

电脑 访问 github提示 找不到网页,处理方案

1、找到 本机的 host文件 例如 windows 的 一般在 C:\Windows\System32\drivers\etc\hosts 用管理员身份打开 hosts 文件 如果文件中没有 github的配置&#xff0c;需要自己手动添加上去&#xff1b; 如果有&#xff0c;则需要 检查 github.com 与 github.global.ssl.fastly.…

Linux系统中的网络管理

1.RHEL9版本中&#xff0c;使用nm进行网络配置&#xff0c;ifcfg不再是网络配置文件的主存储&#xff0c;样式仍然可用&#xff0c;但它不再是NetworkManger存储新网络配置文件的默认位置&#xff0c;RHEL以key-file格式在etc/NetworkManger/system-connections/中存储新的网络…

AI技术深度解析:从移动芯片到AIoT的全面突破

作为全球无线通信技术和半导体解决方案的重要参与者,高通始终将技术创新作为核心驱动力,在移动通信、物联网(IoT)、汽车电子、AI计算等领域占据关键地位。本文将从其核心产品线、技术突破、应用场景及未来布局四个维度,客观解析高通的技术积累与行业角色。 一、核心产品线…

使用CS Roofline Toolkit测量带宽

使用CS Roofline Toolkit测量带宽 工程下载&#xff1a;使用CS Roofline Toolkit测量带宽-案例工程文件&#xff0c;也可以按照下面的说明使用git clone下载 目录 使用CS Roofline Toolkit测量带宽0、Roofline模型理解1、CS Roofline Toolkit下载1.1、设置代理1.2、git clone下…

EAGLE代码研读+模型复现

要对代码下手了&#xff0c;加油(ง •_•)ง 作者在他们自己的设备上展现了推理的评估结果&#xff0c;受第三方评估认证&#xff0c;EAGLE为目前最快的投机方法&#xff08;虽然加速度是评估投机解码方法的主要指标&#xff0c;但其他点也值得关注。比如PLD和Lookahead无需额…

基于SFC的windows修复程序,修复绝大部分系统损坏

效果:可以自动修复大部分由系统文件损坏而导致的错误 例如:系统应用无法打开 系统窗口(例如开始菜单)无法使用 电脑蓝屏或者卡死.....文章 01技术背景 Windows自带了一个SFC命令行应用程序,可以检查大部分的系统文件错误,以及复这些文件 其中自动检查所有系统文件&#x…

liunx日志问题

一、日志定向 Linux 系统的日志配置文件&#xff08;如/etc/syslog.conf或/etc/rsyslog.conf &#xff09;中&#xff0c;用于定义系统日志的记录规则&#xff0c;决定哪些类型的日志消息会被记录到特定的日志文件中。 *.info;mail.none;authpriv.none;cron.none /va…

2.凸包优化求解

1.减而治之(Decrease and Conquer) 插入排序 典型的减而治之算法就是插入排序方法 插入排序法: 在未排序中选择一个元素&#xff0c;插入到已经排序号的序列中 将凸包也采用减而治之的方法 2.In-Convex-Polygon Test 怎么判断引入的极点存在于多边形里面还是外面&#xff1…

系统思考:危机中的转型机遇

“危机不仅是挑战&#xff0c;更是转型的机会” 每当大事发生&#xff0c;很多企业老板常常被眼前的困境压得喘不过气&#xff0c;焦虑与压力让人难以思考长远。特别是在危机面前&#xff0c;大家忙于应对眼前的风险&#xff0c;却忽略了背后隐藏的机遇。而危机&#xff0c;恰…

大模型Rag - 如何评估Rag

一.RAG流程与评估标准补充 RAG&#xff08;Retrieval-Augmented Generation&#xff09;是一种结合检索与生成的问答架构。为了确保系统效果&#xff0c;需要从以下三个角度对其评估&#xff1a; 回顾RAG流程 用户提出问题 → 系统检索相关上下文 → 基于上下文由大语言模型…

Linux RT RT RT

RT的最终目的是尽可能多的让原来系統不可抢占的部分变成可抢占&#xff0c;让高优先级的程序先跑。这里的rt引入了一个deadline的说法&#xff0c;此时的实时性是保证在最大一个时间间隔内&#xff0c;程序被执行。比如每100ms算法做一次决策。 所以此时面临着几座大山…

演员柳琦正式加入创星演员出道计划,开创演艺事业新天地

4月18日&#xff0c;演员柳琦正式加入“创星演员出道计划”&#xff0c;不仅得到参演都市爱情喜剧《和我结婚吧》角色的机会&#xff0c;还获得文旅精品网剧《醉梦灵州》的出演机会&#xff0c;自此开启全新影视之路。对表演艺术极具天赋的柳琦&#xff0c;相信未来可以凭借自身…

16.Chromium指纹浏览器开发教程之WebGPU指纹定制

WebGPU指纹概述 WebGPU是下一代的Web图形和计算API&#xff0c;旨在提供高性能的图形渲染和计算能力。它是WebGL的后继者&#xff0c;旨在利用现代GPU的强大功能&#xff0c;使得Web应用能够实现接近原生应用的图形和计算性能。而且它是一个低级别的API&#xff0c;可以直接与…

HTTP:九.WEB机器人

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

Vue3+TS中svg图标的使用

安装依赖 pnpm i vite-plugin-svg-icons -D配置引入 vite.config.ts ... import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from node:pathconst svgIconsPlugin createSvgIconsPlugin({iconDirs: [path.resolve(process.cwd(), src/assets/icons)]…

【java实现+4种变体完整例子】排序算法中【堆排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是堆排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、堆排序基础实现 原理 基于二叉堆结构&#xff08;最大堆&#xff09;&#xff0c;通过以下步骤实现排序&#xff1a; 构建最大堆&#xff1a;将…