类和结构体

与其他编程语言不同,swift不要求为自定义类和结构创建独立的接口和实现文件.所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口

类和结构体对比

Swift中类和结构体很多相同点:

  • 定义属性泳衣存储值
  • 定义方法用于提供功能
  • 定义下标操作用于通过下标语法访问他们的值
  • 定义构造器用于设置初始值
  • 通过扩展增加默认实现之外的功能
  • 遵循协议提供某种标准功能

Swift中与结构体相比,类还拥有以下的附加功能:

  • 继承允许一个类继承另一个类的特征
  • 类型转换允许在运行时检查和解释一个类实例的类型
  • 析构器允许一个类实例释放任何被其所被分配的资源
  • 引用计数允许对一个类的多次引用

注意

类通过引用计数进行多次引用,结构体通过复制的方式在代码中传递,不使用引用计数

定义语法

通过关键之classstruct来分别标识类和结构体

类和结构体名使用首字母大写的方式进行命名

//定义一个结构体 描述显示器屏幕分辨率
struct Resolution {
    var width = 0
    var height = 0
    //当这两个属性被初始化为整数 0 的时候,它们会被推断为 Int 类型。
}

//定义一个类 描述视频显示器的特定模式
//四个变量存储属性
class VideoMode {
    var resolution = Resolution()//分辨率 结构体
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

存储属性是被捆绑存储在类或结构体中的常量或变量。

类和结构体实例

初始化结构体或类的实例

let someResolution = Resolution()
let someVideoMode = VideoMode()

通过这种方式创建类或者结构体实例,属性都会被初始化为默认值.

属性访问

通过点语法访问实例属性。

//访问结构体属性
print("The width of someResolution is \(someResolution.width)")
// 打印 "The width of someResolution is 0"

//访问变量属性
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// 打印 "The width of someVideoMode is now 1280"

在OC中是不能直接设置结构体子属性值,swift中可以直接设置比如resolution.width属性值,在oc中我们需要给整个结构体resolution设置新值

结构体类型成员逐一构造器

所有结构体都有一个自动生成的成员逐一构造器,用来初始化新结构体成员的属性

//通过属性名称
let vga = Resolution(width:640, height: 480)

类是没有这个成员构造器的

结构体和枚举时值类型

值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝

Swift中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现

swift中,所有结构体和枚举类型都是值类型。因此,它们的实例以及实例中包含的值类型属性,在传递时都会被复制

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide")// "cinema is now 2048 pixels wide"
print("hd is still \(hd.width) pixels wide")//"hd is still 1920 pixels wide"

在对结构体进行赋值的时候,进行了拷贝,cinema和hd是完全不同的两个实例,因此改变了cinema的宽对hd没有影响

枚举也是值类型,遵循相同的行为准则

注意

标准库中定义的集合,例如数组、字典和字符串,都对赋值进行了优化以降低性能成本。新集合不会立即复制,而是跟原集合共享同一份内存,共享同样的元素。在集合的某个副本要被修改之前,才会复制他的元素。而在你的代码中看起来就像是立即发生了复制

类是引用类型

与值类型不同,引用类型在传递时,值不会被拷贝.因此,引用的是已存在的实例本身而不是其拷贝

let tenEighty = VideoMode()
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")//30.0

类是引用类型,所以tenEightalsoTenEight实际上引用的是相同的VideoMode实例
注意:
虽然alsoTenEighty为常量但是仍然可以改变alsoTenEighty.frameRate因为这两个常量的值并未改变,这个常量的值存储的并不是ViewMode的实例,而是对其的引用.

恒等运算符

等价于 === 不等价于 !== 用来检测两个变量或常量是否引用同一个实例

=====的不同:
“等价于”表示两个类类型(class type)的常量或者变量引用同一个类实例。
“等于”表示两个实例的值“相等”或“相同”,判定时要遵照设计者定义的评判标准

指针

一个引用实例的swift常量或者变量,与C指针类似,但是并不直接指向某个内存地址,也不需要用*表明在创建引用.

类和结构体的选择

字符串、数组、字典类型的赋值和复制行为

因为swift中很多基本类型,StringArrayDictionary类型均以结构体的形式实现,赋值给新的常量变量或者传入函数方法中的时候会被拷贝

在OC中NSStringNSArrayNSDictionary是以类的形式实现,不会发生值拷贝而是传递引用

Swift会在绝对必要时才执行实际拷贝,确保性能最优,因此我们没有必要回避赋值来增加性能