XZ_Swift之Swift面向对象

本文深入讲解Swift中的构造函数,包括构造函数的执行顺序、构造函数的基础、重载和重写等概念,以及如何解决初始化过程中可能遇到的问题。

Swift面向对象
1、关于命名空间
在 Swift 中,默认同一个项目中,所有的类都是共享的,可以直接访问,不需要 import
所有对象的属性 var,也可以直接访问到
在Swift中,所有类都默认有一个命名空间,就是项目名称
同一个Person类,从属于不同的命名空间!
OC定义类的时候,会有前缀:NS、XZ、WY…

2、必选属性的构造函数
2.1构造函数的执行顺序
a.构造函数的目的:给自己的属性分配空间并且设置初始值
b.调用父类构造函数之前,需要先给本类属性设置初始值
c.调用父类的‘构造函数’,给父类的属性分配空间设置初始值
NSObject 没有属性,只有一个成员变量 ‘isa’

3、在定义类并且初始化的时候可能会遇到的问题
3.1 Class ‘Person’ has no initializers
‘Person’ 类没有 ‘初始化器s’,构造函数,可以有多个,默认的是 init
3.2 Overriding declaration requires an ‘override’ keyword
重‘写’ -> 父类有这个方法,子类重新实现,需要 override 关键字
3.3 Property ‘self.name’ not initialized at super.init call
在调用父类 super.init 的时候,没有给 self.name 初始化 -> 分配空间,设置初始值!

4、构造函数基础
构造函数 是一种特殊的函数
* 主要用来在创建对象时初始化对象
* 为对象 成员变量 设置初始值
在 OC 中的构造函数是 initWithXXX,在 Swift 中由于支持函数重载,所有的构造函数都是 init

5、重载和重写的区别
5.1 重载 overload 的概念
-函数名相同
-参数类型和个数不同
-重’载’:好处 - 可以从外部给自己的属性设置初始值
-OC 没有重载,都是initWithXXX
-如果重载了构造函数,并且没有实现父类的 init 方法,系统不再提供 init() 构造函数(默认是会有的!) — 因为默认的构造函数,不能给本类的属性分配空间!

5.2 重写 override 的概念
-父类存在相同的方法
-子类重新编写父类的方法的实现

构造函数的作用
-分配空间 alloc
-设置初始值 init

// 实例化 person
// () -> alloc/init
// Swift 中对应一个函数 init() 构造函数
// 作用:给成员变量分配空间,初始化成员变量
let p = Person()
print(p.name)
// 先定义一个 Person 类继承自 NSObject,然后定义一个 Student 类继承自 Person,在 Person 类的 init 方法中,打印 ‘person init’,在 Student 类的 init 方法中,打印 ‘student init’,在控制器中定义以下代码:
let s = Student()
print(s.name + "-----" + s.no)
打印的结果是:
student init 
person init  
张三-----101  

说明调用的顺序是,显示当前类的init方法,然后是父类Person的init方法,然后是父类NSObject的init方法

下图很好的诠释了构造函数的作用
这里写图片描述

小结
-非 Optional 属性,都必须在构造函数中设置初始值,从而保证对象在被实例化的时候,属性都被正确初始化
-在调用分类构造函数之前,必须保证本类的属性都已经完成初始化
-Swift 中的构造函数不用写 func
-Override 重写:-父类存在相同的方法,子类重新编写父类方法的实现。

// Person 类 重载 构造函数
    var name:String
    init(name:String) {

        // 使用参数的 name 设置给属性
        self.name = name
        // 调用父类的构造函数
        super.init()
    }
// Student 类 重载 构造函数
// 学号
    var no:String

    init(name: String,no: String) {
        self.no = no
        // 调用父类方法,给 name 初始化
        super.init(name: name)
    }

重载构造函数
Swift中支持函数重载,同样的函数名,不一样的参数类型
// 如果希望在创建对象时,直接为属性设置需要的数值,可以重载构造函数
init(name:String) {
self.name = name
super.init()
}

调用构造函数
// 一旦重载了构造函数,系统不再提供默认的 ’( )’ 构造函数
// let p = Person( )
// 使用重载的构造函数创建对象,并且设置指定值
let p = Person(name: “张三”)

注意事项
-如果重载了构造函数,但是没有实现默认的构造函数 init(),则系统不再提供默认的构造函数;
-原因,在实例化对象时,必须通过构造函数为对象属性分类空间和设置初始值,对于存在必选参数的类而言,默认的 init( ) 无法完成分配空间和设置初始值的工作

`xz_dec_run` 是 XZ 解压缩库中的一个关键函数,用于执行实际的解压缩操作。在某些情况下,调用 `xz_dec_run` 时可能会遇到错误,例如返回 `XZ_DATA_ERROR` 或 `XZ_BUF_ERROR`,这通常表示输入数据损坏、缓冲区不足或解压缩流程配置不当。这类问题在嵌入式系统中尤为关键,尤其是在使用 MTD(Memory Technology Device)设备时,如 NAND 或 NOR Flash 存储器,数据完整性问题可能导致解压缩失败 [^3]。 ### 常见问题与解决方法 #### 1. **输入数据损坏或不完整** 如果输入流在传输或存储过程中被损坏,`xz_dec_run` 会返回 `XZ_DATA_ERROR`。这通常发生在固件更新失败、文件系统损坏或存储介质错误的情况下。 **解决方法:** - 确保输入数据完整无损,可以通过校验(如 CRC32)验证数据完整性。 - 在嵌入式系统中,启用 MTD 层的 ECC 校正功能,确保数据读取过程中能够自动修复位翻转问题 [^3]。 #### 2. **缓冲区大小不足** `xz_dec_run` 需要足够的输入输出缓冲区来处理数据。如果缓冲区太小,可能导致 `XZ_BUF_ERROR`。 **解决方法:** - 确保输入缓冲区 (`in` 指针) 输出缓冲区 (`out` 指针) 足够大,建议使用 4KB 或更大的缓冲区。 - 动态分配缓冲区以适应不同大小的数据块。 #### 3. **解压缩器未正确初始化** 调用 `xz_dec_run` 前必须正确调用 `xz_dec_init()` 初始化解压缩器。如果跳过此步骤或初始化失败,可能导致运行时错误。 **解决方法:** - 在调用 `xz_dec_run` 之前,确保 `xz_dec_init()` 成功执行。 - 检查返回值,如果初始化失败,应释放资源并返回错误码。 #### 4. **流式处理不当** `xz_dec_run` 支持流式解压缩,但如果未正确处理输入/输出指针缓冲区状态,可能导致解压缩不完整或死循环。 **解决方法:** - 正确管理 `in_pos` `out_pos` 指针,确保每次调用 `xz_dec_run` 时更新缓冲区偏移量。 - 在读取完所有输入数据后,检查是否所有输出数据都已处理完毕。 #### 5. **内存分配失败** `xz_dec_run` 可能依赖动态内存分配,如果内存不足,可能导致解压缩失败。 **解决方法:** - 使用自定义内存分配器(如 `ISzAlloc` 接口)来管理内存分配,确保在资源受限的环境中也能正常工作 [^2]。 - 在嵌入式系统中预留足够的内存用于解压缩操作。 ### 示例代码:使用 xz_dec_run 解压缩 ```c #include <stdio.h> #include <stdlib.h> #include "xz.h" #define BUF_SIZE 4096 int decompress_xz(const char *in_file, const char *out_file) { FILE *fin = fopen(in_file, "rb"); FILE *fout = fopen(out_file, "wb"); if (!fin || !fout) { return -1; } struct xz_dec *state; struct xz_buf buf; uint8_t in[BUF_SIZE]; uint8_t out[BUF_SIZE]; state = xz_dec_init(XZ_DYNALLOC, 0); if (!state) { fclose(fin); fclose(fout); return -1; } buf.in = in; buf.in_size = 0; buf.out = out; buf.out_size = BUF_SIZE; while (1) { size_t in_read = fread((void *)buf.in + buf.in_pos, 1, BUF_SIZE - buf.in_pos, fin); buf.in_size = buf.in_pos + in_read; enum xz_ret ret = xz_dec_run(state, &buf); fwrite(out, 1, buf.out_pos, fout); buf.out_pos = 0; if (ret == XZ_STREAM_END) { break; } else if (ret != XZ_OK) { xz_dec_end(state); fclose(fin); fclose(fout); return -1; } if (in_read == 0 && buf.in_pos == buf.in_size) { break; } } xz_dec_end(state); fclose(fin); fclose(fout); return 0; } ``` ### 调试建议 - 使用日志记录每次调用 `xz_dec_run` 的返回值缓冲区状态,有助于定位问题。 - 在嵌入式设备中,可以尝试使用 `xz` 工具链在主机端验证压缩文件的完整性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值