Swift——类与结构体

一.结构体

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

结构体定义如下:

Swift 复制代码
struct Person {
    var name:String
    var age:Int
}

1.结构体的初始化

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

如图:

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

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

二.类

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

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

1.类的初始化

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

初始化如图:

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

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

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

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

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

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

如图:

Swift 复制代码
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编译相关命令:

css 复制代码
//分析输出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
相关推荐
爱吃香菜---www几秒前
Scala中字符串
开发语言·后端·scala
睎zyl5 分钟前
scala统计词频
开发语言·后端·scala
西猫雷婶6 分钟前
python学opencv|读取图像
开发语言·人工智能·python·opencv·计算机视觉
Betty_蹄蹄boo6 分钟前
scala统计词频
开发语言·c#·scala
yivifu20 分钟前
不玩PS抠图了,改玩Python抠图
开发语言·python·opencv
i7i8i9com23 分钟前
baomidou Mabatis plus引入异常
java·开发语言·mybatis
白雪落青衣41 分钟前
2627函数防抖
开发语言·前端·javascript
nuclear20111 小时前
Python 在Excel中插入、修改、提取和删除超链接
开发语言·python
续写少年!1 小时前
自定义注解
java·开发语言
苹果酱05671 小时前
通俗理解人工智能、机器学习和深度学习的关系
java·开发语言·spring boot·mysql·中间件