前言

  • Swift 语言有两种基本的数据类型,即类(class)和结构体(struct),class 这样的概念大家不会陌生,而 struct 也并不是什么新的概念,在 Objective-C 和 C 中也有 struct,不过 Swift 将 struct 提升到一个更高更重要的层次,甚至 Swift Foundation 框架的 SDK,诸如 String,Array,Dictionary 都是基于 struct 实现的。

  • 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

  • 和 class 一样,struct 也可以定义属性和方法,同样 struct 也要求完整初始化,即保证初始化过程中每一个 non-optional 属性要赋予明确的初始值。

  • 结构体是值类型,并且只有在赋予变量或常量,或者被函数调用时才被赋值。

1、结构体的创建

  • 结构体基本结构

    struct 结构体名 {
    
        var 或 let 字段名 = 初始化值
    var 或 let 字段名: 类型
    }
    struct Student {
    
        var age = 0
    } var stu = Student() /// struct 结构体关键字
    /// Student 结构体名称 /// student() 创建一个结构体变量

1.1 标准定义

  • 结构体的定义

    • 定义结构体字段时可以直接定义一个字段名,并且给字段名赋初始值。或者只定义一个字段名,不赋初始值,但是不赋初始值的字段在创建结构体变量时必须赋初始值。

      struct Student {                              
      
          var name: String                           // 只定义一个字段名,不赋初始值
      var age = 0 // 定义一个字段名,并且给字段名赋初始值
      }
  • 结构体的使用

    • 创建结构体变量时,结构体的字段都必须都有初始值,否则会报错。

      let s = Student(name: "appple", age: 8)        // 创建结构体变量时初始化结构体的字段
      
      print("\(s.name), \(s.age)")                   // 结构体类型变量值的调用

1.2 基本定义

  • 结构体的定义

    • 每个字段名都赋初始值。

      struct BookInfo {                               
      
          var id: Int = 0                            // 每个字段名都赋初始值
      var name: String = "Default"
      var author: String = "Default"
      var rootType: String = "Default"
      }
  • 结构体的使用

    • 创建结构体变量时,结构体的字段都必须都有初始值,否则会报错。

      let book = BookInfo()                          // 创建结构体变量时不再需要初始化结构体的字段
      
      print("\(book.id), \(book.name), \(book.author), \(book.rootType)")     // 结构体类型变量值的调用

2、结构体的方法

2.1 定义枚举的方法

  • 枚举方法的定义

    struct markStruct1 {
    
        var mark1: Int = 0
    var mark2: Int = 0
    var mark3: Int = 0 func sum(a: Int) -> Int { // 定义方法 return (self.mark1 + self.mark2 + self.mark3) * a
    }
    }
  • 枚举方法的使用

    let mark1 = markStruct1(mark1: 11, mark2: 22, mark3: 33)
    
    print(mark1.sum(a: 2))                                       // print 132

2.2 自定义构造方法

  • 与 class 的初始化方法不同点

    • struct 的 init 并没有便利初始化(convenience init)方法。
    • 因为 struct 没有继承,所以 struct 的 init 也不需要 required 关键字。
  • 这样对比,struct 的初始化方法比起 class 的初始化方法来说要简单的多,因为 struct 只有指定初始化,struct 只需要保证指定初始化过程中每个非可选属性都赋值,没有复杂的初始化规则和规范,struct 相比于 class 也显得更加简单,更有亲和力。

  • 一旦我们自定义了初始化器,系统自动的初始化器就不起作用了,如果还需要使用到系统提供的初始化器,在我们自定义初始化器后就必须显式的定义出来。

  • 可失败构造方法

    struct markStruct2 {
    
        var mark1: Int
    var mark2: Int
    var mark3: Int init?(mark1: Int, mark2: Int, mark3: Int) { // 可失败(failable)的构造方法 self.mark1 = mark1
    self.mark2 = mark2
    self.mark3 = mark3
    }
    }
  • 普通构造方法

    struct markStruct3 {
    
        var mark1: Int
    var mark2: Int
    var mark3: Int init(mark1: Int, mark2: Int, mark3: Int) { // 普通的构造方法 self.mark1 = mark1
    self.mark2 = mark2
    self.mark3 = mark3
    }
    }
  • 使用

    let mark2 = markStruct2(mark1: 11, mark2: 22, mark3: 33)
    print("\(mark2?.mark1 ?? 0), \(mark2?.mark2 ?? 0), \(mark2?.mark3 ?? 0)") // print 11, 22, 33 let mark3 = markStruct3(mark1: 11, mark2: 22, mark3: 33)
    print("\(mark3.mark1), \(mark3.mark2), \(mark3.mark3)") // print 11, 22, 33

3、Swift 中枚举、结构体和类的比较

3.1 在 Swift 中类型引用和值引用的区别

  • 对于类型引用(class reference),将变量 a 赋值给变量 b,即 b = a,这样的赋值语句仅仅将 b 的指针与 a 的指针一样,指向同一块内存区域,此时改变 b 的值,a 也会跟着改变;

  • 对于值引用(value reference),赋值语句 b = a 处理的过程是开辟一个新的内存 b,将 a 变量的内容拷贝后存放到内存 b,这时 ab 完全没有关系的两个变量,对 b 的改变不会影响到 a,反之亦然。

  • 在 Objective-C 时代,我们对类型引用和值引用就有了一定的了解,例如在 Objective-C 中常用的 NSArray, NSDictionary, NSString, UIKit 等都是类型引用;而 NSInteger, CGFloat, CGRect 等则是值引用。

  • 显然,在 Objective-C 中,引用类型占据了很大的比重,现在使用 Swift 开发应用程序,开发者需要转变观念,因为 struct 在 Swift 变得越来越重要,观念的转变不仅在于多使用 struct,还要求开发者理解 struct 的原理,优点及缺点。

3.2 枚举、结构体、类的共同点

  • 定义属性用于存储值,枚举只能定义计算属性
  • 定义方法以提供功能
  • 定义下标,以便用下标语法来访问它们的值
  • 定义初始化程序,以创建它们的初始状态
  • 支持扩展增加功能,来扩展它们的默认实现
  • 可以遵循协议,来完成特定标准功能

3.3 枚举、结构体、类的区别

  • 类是引用类型,而枚举和结构体是值类型
  • 类有继承功能,而枚举和结构体没有继承的功能

3.4 类特有的功能

  • 继承
  • 允许类型转换
  • 析构方法释放资源
  • 引用计数

3.5 该如何选择

  • 关于在新建一个类型时如何选择到底是使用值类型还是引用类型的问题其实在理解了两者之间的区别后是非常简单的,在这苹果官方已经做出了非常明确的指示

    • 当你使用 Cocoa 框架的时候,很多 API 都要通过 NSObject 的子类使用,所以这时候必须要用到引用类型 class。
    • 在其他情况下,有下面几个准则。
  • 1)什么时候该用值类型

    • 要用 == 运算符来比较实例的数据时
    • 你希望那个实例的拷贝能保持独立的状态时
    • 数据会被多个线程使用时
  • 2)什么时候该用引用类型(class)

    • 要用 == 运算符来比较实例身份的时候
    • 你希望有创建一个共享的、可变对象的时候

Swift Struct 结构体的更多相关文章

  1. iOS - Swift Struct 结构体

    1.Struct 的创建 1.1 基本定义 结构体的定义 // 定义结构体数据类型 struct BookInfo { // 每个属性变量都必须初始化 var ID:Int = 0 var Name: ...

  2. C# Struct结构体里数组长度的指定

    typedef struct Point{ unsigned short x; unsigned short y; }mPoint;//点坐标 typedef struct Line{ mPoint ...

  3. C#基础--struct(结构体)

    结构体和类有点类似    我们定义一个类的时候    是class   类名   定义结构体的时候是 struct   结构体名 结构体的写法 struct Point { // public int ...

  4. 1.0 基础、标示符、常量、数据类型(enum 枚举,struct 结构体)、操作符、循环、数组

    一.程序 现实生活中,程序是指完成某些事务的一种既定方法和过程,可以把程序看成是一系列动作执行过程的描述. 在计算机世界,程序是指令,即为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集 ...

  5. C#语言struct结构体适用场景和注意事项

    在C#语言中struct结构体和class之间的区别主要是值类型和引用类型的区别,但实际上如果使用不当是非常要命的.从Win32时代过来的人对于struct一点不感觉陌生,但是却反而忽略了一些基本问题 ...

  6. C语言 Struct 结构体在 Java 中的体现

    大一整个学期完成了 C 语言的学习,大二就进入了Java 的学习. 和C语言一样,我们都会尝试写一个小小的学生管理系统什么的,学习过 C 语言同学知道,在管理系统中 Struct 结构体是个很好用的东 ...

  7. go struct结构体

    struct结构体 用来自定义复杂数据结构 struct里面可以包含多个字段(属性),字段可以是任意类型 struct类型可以定义方法,注意和函数的区分 struct类型是值类型 struct类型可以 ...

  8. struct 结构体解析(原)

    (一)基本概念 结构体是一个或是多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组合在一个名字之下.我们将关键字struct引入了结构声明中.结构声明包含在花括号内的一系列声明组成 ...

  9. struct结构体在c和c++中的差别

    非常多次遇到这个struct的问题,今天在这里简单总结一下我的理解 一.struct在C 中的使用 1.单独使用struct定义结构体类型 struct Student { int id; int n ...

随机推荐

  1. P1993 小K的农场

    P1993 小K的农场比较裸的差分约束,只是我判负环的时候sb了... 有负环意味着无解 #include<iostream> #include<cstdio> #includ ...

  2. 005.Ceph文件系统基础使用

    一 Ceph文件系统 1.1 概述 CephFS也称ceph文件系统,是一个POSIX兼容的分布式文件系统. 实现ceph文件系统的要求: 需要一个已经正常运行的ceph集群: 至少包含一个ceph元 ...

  3. 从小白到区块链工程师:第一阶段:Go语言环境的搭建(1)

    一,Golang语言简介 2009年由谷歌公司推出,由C语言之父Ken Thompson主导研发.Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语 ...

  4. SpringMVC(二六) SpringMVC配置文件中使用mvc:view-controller标签

    在springmvc中使用mvc:view-controller标签直接将访问url和视图进行映射,而无需要通过控制器. 参考springmvc.xml内容: <?xml version=&qu ...

  5. shell编程第一天

    shell编程基础 脚本:简单来说就是一条条的文字命令(一些指令的堆积)Shell属于内置的脚本 1.程序开发效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理) 2.语法简单,代码写起来 ...

  6. asp.net core 依赖注入实现全过程粗略剖析(1)

    转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/ 常用扩展方法 注入依赖服务: new ServiceCollection().AddSingle ...

  7. MacOs brew 命令行安装常见工具

    brew类似ubuntu系统下的apt-get的功能 安装方法:  在Mac中打开Termal:  输入命令: ruby -e "$(curl -fsSL https://raw.githu ...

  8. VMware5.5-虚拟机的迁移和资源分配

    虚拟机的迁移 迁移:将虚拟机从一台主机(或数据存储)移到另一台主机(或数据存储). 迁移类型: 冷迁移 迁移处于关闭状态的虚拟机. 挂起 迁移处于挂起状态的虚拟机. vMotion 迁移处于开启状态的 ...

  9. 在UnrealEngine中用Custom节点实现毛玻璃的效果

    本人在论坛上找到了一篇实现毛玻璃效果的文章:https://forums.unrealengine.com/showthread.php?70143-So-Blurred-glass-material ...

  10. BZOJ.5251.[八省联考2018]劈配mentor(最大流)

    BZOJ 洛谷 对于每个人,每次枚举一个志愿看是否能增广即可. 对于第二问,可以保留第一问中\(n\)次增广前后的\(n\)张图,二分,在对应图上看是否能增广即可. 貌似匈牙利的某种写法比网络流优多了 ...