存储属性和计算属性
存储属性
存储属性,把常量或变量的值作为实例的一部分。
存储属性的作用是把常量或变量的值作为实例的一部分,使用var关键字定义的属性为变量存储属性,使用let关键字定义的属性为常量存储属性。
计算属性
计算属性,它计算一个值,类似于方法的功能,提供了一个处理数据的入口与出口。
计算属性可以用于类、结构和枚举里,存储属性只能用于类和结构体里。
计算属性不直接存储值,而是提供一个getter来获取值,然后用一个可选的setter来间接设置其他属性或变量值,getter方法通过访问触发,setter方法通过赋值触发。
例:
class newClass {
var givenName = "张"
var firstName = "小龙"
var allName: String {
get {
return givenName + firstName
}
}
}
在Swift中,类在初始化的时候它的属性必须都被初始化。如果不想设置某个属性的默认值,则可使用"?"把它加入可选链中,声明为可选类型,如
var name:String?
。
枚举
枚举是一组有共同特性的数据的集合。
与OC中的枚举不同的是,Swift的枚举成员在被创建时不会有默认的整形值,而是其枚举的类型。
定义
使用 enum 关键词来创建枚举并且把它们的整个定义放在一对大括号内。
枚举定义时可以设置其 原始值 ,原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的:
enum 枚举类型名称: 原始值类型 {
case 枚举值1
case 枚举值2
// ...
}
例如:
// 整数
enum Movement:Int {
case left
case right
case top
case bottom
}
// 也可以简写成
enum Movement:Int {
case left,right,top,bottom,
}
当使用整数作为原始值时,隐式赋值的值依次递增1。如果第一个值没有被赋初值,将会被自动置为0。
// 字符串
enum Area: String {
case DG = "dongguan"
case GZ = "guangzhou"
case SZ = "shenzhen"
}
也可以设置其 相关值 ,相关值在创建一个基于枚举成员的新常量或变量时才会被设置(类似于对象中的属性值),如:
enum Student{
case Name(String)
case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("学生的名字是: \(studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。")
}
嵌套枚举
枚举中可以嵌套枚举,如:
enum Area {
enum DongGuan {
case NanCheng
case DongCheng
}
enum GuangZhou {
case TianHe
case CheBei
}
}
print(Area.DongGuan.DongCheng)
属性
枚举中不能直接添加属性,但是可以创建计算属性,如:
enum Device {
case iPad, iPhone
var year: Int {
switch self {
case iPhone: return 2007
case iPad: return 2010
}
}
}
方法
Swift的枚举中也可以添加实例方法和类方法,具体参看上一篇文章。
结构体
结构体是构建代码所用的一种通用且灵活的构造体。
Swift中的结构体与C++和OC中的结构体有很大的差别,C++和OC中的结构体只能定义一组相关的成员变量,而Swift中的结构体不仅可以定义属性,还可以定义方法。因此,我们可以把Swfit结构体看做是一种轻量级的类。
Swift语言却非常重视结构体,把结构体作为实现面向对象的重要手段。
与类的区别
Swift中类和结构体的不同处在于:
结构体不具有继承性
结构体不具备运行时强制类型转换
结构体不具备使用析构器的能力
结构体不具备使用引用计数的能力
定义
结构体定义使用struct关键字
struct 结构体名 {
……
}
构造函数
- 默认情况下,系统会为每一个结构体提供一个默认的构造函数,并且该构造函数,要求给每一个成员属性进行赋值
- 构造函数都是以 init 开头,并且构造函数不需要返回值
- 在构造函数结束时,必须保证所有的成员属性都被初始化
例:
struct MarkStruct {
var mark1: Int
var mark2: Int
var mark3: Int
// 自己的构造函数
init(whStr:String) {
let arr = whStr.components(separatedBy: ",")
let m1 = arr[0]
let m2 = arr[1]
let m23= arr[2]
self.mark1= Int(m1) ?? 0
self.mark2= Int(m2) ?? 0
self.mark3= Int(m3) ?? 0
}
}
// 使用
// 调用自动生成的构造函数
var marks = MarkStruct(mark1: 98, mark2: 96, mark3: 100)
// 调用增加的构造函数
var marks = MarkStruct(whStr: "98,96,100")
方法
结构体中的实例方法和类方法的使用可以参考上一篇文章。
当需要在方法中修改到结构体和枚举的属性值时(一般不建议这么做),需要在方法前加上
mutating
关键字,如:struct Size { var width:Double var height:Double = 0.0 mutating func changeWidth(width: Double) { self.width = width } }
类
类是构建代码所用的一种通用且灵活的构造体,可以为类定义属性(常量、变量)和方法。
Swift 并不要求为自定义类去创建独立的接口和实现文件。所要做的是在一个单一文件中定义一个类,系统会自动生成面向其它代码的外部接口。
类的特性
类与结构体的共同特性有:
- 定义属性用于存储值
- 定义方法用于提供功能
- 定义附属脚本用于访问值
- 定义构造器用于生成初始化值
- 通过扩展以增加默认实现的功能
- 符合协议以对某类提供标准功能
此外,类还有以下的特性:
- 允许一个类继承另一个类的特征
- 类型转换允许在运行时检查和解释一个类实例的类型
- 解构器允许一个类实例释放任何其所被分配的资源
- 引用计数允许对一个类的多次引用
定义
Swift中使用class关键字来定义一个类,格式如下:
class 类名 {
……
}
构造函数
类的构造函数的定义与使用与结构体大体相似。
不同的是,如果在类中自定义了构造函数,则会覆盖掉自动生成的构造函数,且自动生成的构造函数中不强制要求给每个属性进行赋值。
方法
类中的实例方法与类方法的使用可以参考上一篇文章。
恒等运算符
类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。
恒等运算符(===
和!==
)能够判定两个常量或者变量是否引用同一个类实例。
类和结构体的选择
结构体实例总是通过值传递,类实例总是通过引用传递。
即:
结构体赋值时可以看成是值的拷贝,
类赋值时可以看成是类的实例的地址的传递。
在考虑一个项目的数据构造和功能的时候,就需要决定每个数据构造是定义成类还是结构体。
当符合一条或多条以下条件时,请考虑构建结构体:
- 结构体的主要目的是用来封装少量相关简单数据值。
- 有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
- 结构体不需要去继承另一个已存在类型的属性或者行为。
Swift里更推荐使用值类型变量(struct)而不是引用类型(class)的变量,Swift中许多常见的数据类型、字符串、集合类型,以及结构体和枚举都是值类型而非引用类型,值类型的变量在赋值时会自动进行一次低消耗的值拷贝,对比对象的copy要更加高效而且不存在线程安全问题。