当前位置: 首页 > article >正文

Swift——类与结构体

一.结构体

在swift的标准库中,大部分的类型都是结构体,比如:Int,Double,String,Array,Dictionary等等,它们都是结构体。

结构体定义如下:

struct Person {
    var name:String
    var age:Int
}

1.结构体的初始化

所有结构体都有一个编译器自动生成的初始化器,这样保证了结构体成员都有初始值。

如图:

如果你自定义了一个初始化器,那么编译器就不会生成初始化器,初始化器定义方式如下:

我们在定义结构体初始化时,一定要保证所有的结构体成员都有初始化值,否则会报错。

二.类

类与结构体十分类似,它们的不同点如下:

  1. 类可以继承,结构体不可以继承
  2. 类的实例类型可以通过使用类型转换进行检查和解释
  3. 类有析构函数(deinit()),该函数可以用来释放其分配的资源
  4. 引用计数允许对一个类实例有多个引用
  5. 编译器不会为类自动提供成员初始化器

1.类的初始化

与结构体不同,编译器不会提供初始化器,所以,如果你的类里面的成员没有初始化值,那你需要为类提供一个指定的初始化器,,否则编译不通过。

初始化如图:

也可以创建便捷初始化器,但是使用便捷初始化器,必须先调用主初始化器,如图:

在swift中,指定初始化器和便捷初始化器有以下规则:

规则1:指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性都要初始化完成。 

规则2:指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值。如果不这样做,指定初始化器赋予的新值将被父类中的初始化器所覆盖 

规则3:便捷初始化器必须先委托同类中的其它初始化器,然后再为任意属性赋新值(包括同类里定义的属性)。如果没这么做,便捷构初始化器赋予的新值将被自己类中其它指定初始化器所覆盖。 

规则4:初始化器在第一阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也不能引用 self 作为值。

如图:

class Father {
    var name:String
    var age:Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class Son:Father{
    var height:Double
    var weight:Double = 20
    init(height: Double) {
        print("\(self.weight)")

        self.height = height
        super.init(name: "2", age: 20)//规则1,调用父类初始化器前,自身类成员必须初始化
        show() //规则4 所有属性初始化之后,才可以调用实例方法
        print(self)
        self.name = "222"//规则2,对继承的属性赋新值,必须先委托父类初始化器
        
    }
    func show(){
        print("Son的show方法")
    }
    convenience init() {
        self.init(height:110)
        self.weight = 120//规则3
        self.height = 170
    }

}

可失败初始化器:这种初始化器是当初始化失败时,我们允许类返回nil用来表示类初始化失败,初始化失败的原因可能是外部参数输入不合法,或不满足可初始化的条件,其定义如下:

必要初始化器:在类初始化器前添加required关键字来表示该类的所有子类都必须实现该初始化器。如图:

三.值类型与引用类型

swift里面的类型分为两种:值类型和引用类型

  • 值类型:每个实例都保留了一分独有的数据拷贝,一般以结构体(struct)、枚举(enum)或者 元组(tuple)的形式出现。
  • 引用类型:每个实例共享同一份数据来源,一般以类(class)的形式出现。

1.值类型与引用类型的区别:

值类型的变量在赋值的时候是深拷贝,当一个变量的属性值被修改,另一个变量的值不会变。

引用类型的变量不会直接存储具体的实例对象。

这里可以看见,p1和p2对应的地址是相同的,当修改一个实例对象的属性值,另一个也会被修改。

四.类和结构体的存储位置

引用类型和值类型还有一点不同就是存储位置不同,值类型存储在栈(stack)上,而引用类型存储在堆(heap)上。

五.如何使用结构体和类

因为结构体存储在栈上,而类存储在堆上,因此在创建和销毁上,类消耗的时间和内存会比较多,同时,类是引用类型,在赋值时会有引用计数,这里也会造成成本,因此,创建结构体会比创建类所消耗的时间和内存更少。

使用值类型的时机:

  • 用==运算符比较实例数据时
  • 希望实例被拷贝后仍保持独立状态时
  • 数据会被多个线程使用时

使用引用类型的时机:

  • 用==运算符比较实例身份时
  • 希望创建一个可以共享,可变对象时

五.类的生命周期

1.Swift的编译过程

iOS开发的语言都是通过LLVM进行编译,如图:

  • OC通过clang编译器,编译成IR文件,然后再生成可执行文件.o(这里也就是我们的机器码) 
  • Swift则是通过Swift编译器编译成IR文件,然后在生成可执行文件.o。

Swift编译相关命令:

//分析输出AST
swiftc main.swift -dump-parse


//分析并检查类型输出AST
swiftc main.swift -dump-ast


//生成中间体语言(SIL),未优化
swiftc main.swift -emit-silgen

//生成SIL,优化后
swiftc main.swift -emit-sil

//生成LLVM中间体语言(.ll文件)
swiftc main.swift -emit-ir


//生成LLVM中间体语言(.bc文件)
swiftc main.swift -emit-bc

//生成汇编
swiftc main.swift -emit-assembly

//编译生成可执行.out文件
swiftc -o main.o main.swift


http://www.kler.cn/a/415510.html

相关文章:

  • 2024年一级建造师考试成绩,即将公布!
  • 配置泛微e9后端开发环境
  • 【机器学习】—逻辑回归
  • 【SPIE出版|四大高校联合举办】先进算法与图像处理技术国际学术会议(IC-AAIP 2025)
  • 嵌入式Qt使用ffmpeg视频开发记录
  • systemverilog约束中:=和:/的区别
  • 力扣刷题TOP101:6.BM7 链表中环的入口结点
  • ClickHouse 中利用Map类型存储多key数组并进行高效查询
  • 喜欢发光的自己
  • 【Electron学习笔记(四)】进程通信(IPC)
  • k8s集成skywalking
  • Python 3 教程第40篇(requests 模块)
  • rabbitmq 启动异常问题排查
  • TransVG 代码配置及一些小细节
  • 《 C++ 点滴漫谈: 二 》编程语言之争:从 C 到 C++,两代语言的技术传承与演化,谁更适合你的项目?
  • 青训营-豆包MarsCode技术训练营试题解析九
  • 软件设计模式复习
  • 火语言RPA流程组件介绍--键盘按键
  • Scala学习记录,统计成绩
  • ADAM优化算法与学习率调度器:深度学习中的关键工具
  • 深入学习MapReduce:原理解析与基础实战
  • 认识redis 及 Ubuntu安装redis
  • Figma入门-约束与对齐
  • 【前端开发】小程序无感登录验证
  • windows下使用WSL
  • AI智算-正式上架GPU资源监控概览 Grafana Dashboard