版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.07.29 |
前言
我是swift2.0的时候开始接触的,记得那时候还不是很稳定,公司的项目也都是用oc做的,并不对swift很重视,我自己学了一段时间,到现在swift3.0+已经出来了,自己平时也不写,忘记的也差不多了,正好项目这段时间已经上线了,不是很忙,我就可以每天总结一点了,希望对自己对大家有所帮助。在总结的时候我会对比oc进行说明,有代码的我会给出相关比对代码。
1. swift简单总结(一)—— 数据简单值和类型转换
2. swift简单总结(二)—— 简单值和控制流
3. swift简单总结(三)—— 循环控制和函数
4. swift简单总结(四)—— 函数和类
5. swift简单总结(五)—— 枚举和结构体
6. swift简单总结(六)—— 协议扩展与泛型
7. swift简单总结(七)—— 数据类型
8. swift简单总结(八)—— 别名、布尔值与元组
9. swift简单总结(九)—— 可选值和断言
10. swift简单总结(十)—— 运算符
11. swift简单总结(十一)—— 字符串和字符
12. swift简单总结(十二)—— 集合类型之数组
13. swift简单总结(十三)—— 集合类型之字典
14. swift简单总结(十四)—— 控制流
15. swift简单总结(十五)—— 控制转移语句
16. swift简单总结(十六)—— 函数
17. swift简单总结(十七)—— 闭包(Closures)
18. swift简单总结(十八)—— 枚举
19. swift简单总结(十九)—— 类和结构体
20. swift简单总结(二十)—— 属性
21. swift简单总结(二十一)—— 方法
22. swift简单总结(二十二)—— 下标脚本
23. swift简单总结(二十三)—— 继承
构造过程 - Initialization
这里要说一下构造过程,构造过程是为了使用某个类、结构体或者枚举类型的实例而进行的准备过程。这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务。
构造过程是通过定义构造器(Initialization)
来实现的,这些构造器可以看做是用来创建特定类型实例的特殊方法,swift
中的构造器无需返回返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类实例可以通过析构器(deinitializer)
在类实例释放之前执行特定的清楚工作。
这一篇从下面几个方面讲解:
- 存储型属性的初始值
- 定制化构造过程
- 默认构造器
- 值类型的构造器代理
存储型属性的初始赋值
类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值,存储型属性的值不能处于一个未知的状态。可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。
注意:为存储型属性设置值时,它们的值时被直接设置的,不会触发任何属性观测器(property observer)
。
1. 构造器
构造器在创建某特定类型的新实例时调用,它的最简形式类似于一个不带任何参数的实例方法,以关键字init
命名。
下面我们看一个例子。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
var f = Fahrenheit()
print("temperature is \(f.temperature)")
}
}
struct Fahrenheit {
var temperature : Double
init() {
temperature = 32.0
}
}
下面看输出结果
temperature is 32.0
这个结构体定义了一个不带参数的构造器init
,并在里面将存储型属性temperature
的值初始化为32.0
。
2. 默认属性值
如果一个属性总是使用同一个初始值,可以为其设置一个默认值,无论定义默认值还是在构造器中赋值,最终它们实现的效果是一样的,只不过默认值将属性的初始化和属性的声明结合的更紧密,使用默认值能让你的构造器更简洁和更清晰。
你可以使用更简单的方式在定义结构体Fahrenheit
时为属性temperature
设置默认值,具体如下代码所示。
struct Fahrenheit {
var temperature : 32.0
}
定制化构造过程
你可以通过输入参数和可选属性类型来定制构造过程,也可以在构造过程中修改常量属性。
1. 构造函数
你可以在定义构造器时提供构造函数,为其提供定制化构造所需值的类型和名字。构造器参数的功能和语法跟函数和方法参数相同。
下面看一个简单例子。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let boillingPointOfWater = Celsuis(formFahrenheit: 212.0)
let freezePointOfWater = Celsuis(fromKelvin: 273.15)
print(boillingPointOfWater)
print(freezePointOfWater)
}
}
struct Celsuis {
var temperatureInCelsuis : Double = 0.0
init(formFahrenheit fahrenheit : Double) {
temperatureInCelsuis = (fahrenheit - 32.0) / 1.0
}
init(fromKelvin kelvin : Double) {
temperatureInCelsuis = kelvin - 273.15
}
}
下面我们看结果输出
Celsuis(temperatureInCelsuis: 180.0)
Celsuis(temperatureInCelsuis: 0.0)
可以发现,我们可以定义多个构造器,并且可以设置外部参数和内部参数,这里设置的是两个构造器。
2. 内部和外部参数名
其实,这个功能上个例子已经可以看到,在构造器中设置内部参数和外部参数。如果在定义构造器的时候没有提供参数的外部名字,swift
会为每个构造器的参数自动生成一个和内部名字相同的外部名,就相当于在每个构造参数之前加一个哈希符号。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let color = Color(red: 1.0, green: 1.0, blue: 1.0)
print(color.red)
print(color.green)
print(color.blue)
}
}
struct Color {
var red = 0.0, green = 0.0, blue = 0.0
init(red : Double, green : Double, blue : Double) {
self.red = red
self.green = green
self.blue = blue
}
}
下面看输出结果
1.0
1.0
1.0
3. 可选属性类型
如果你定制的类型包含一个逻辑上允许取值为空的存储型属性,不管是因为它无法在初始化时赋值,还是因为它可以在之后某个时间点可以赋值为空,你都需要将它定义为可选类型optional type
,可选类型的属性将自动初始化为空nil
,表示这个属性是故意在初始化时设置为空的。
看一下下面的例子。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let cheeseQuestion = SurveyQuestion(text: "Do you like me?")
cheeseQuestion.ask()
cheeseQuestion.response = "YES, I do!"
print(cheeseQuestion.response)
}
}
class SurveyQuestion{
var text : String
var response : String?
init(text : String) {
self.text = text
}
func ask(){
print(text)
}
}
下面看输出结果
Do you like me?
Optional("YES, I do!")
这里,response
就是可选属性,当SurveyQuestion
实例化时,它将自动赋值为空nil
,表明暂时不存在此字符串。
4. 构造过程中常量属性的修改
只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值,对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改,不能再子类中修改,下面看一个例子。
class SurveyQuestion{
let text : String
var response : String?
init(text : String) {
self.text = text
}
func ask(){
print(text)
}
}
这里
let text : String
定义了常量属性,并且在构造器中进行了修改。
默认构造器
swift
为所有属性已提供默认值的且自身没有定义任何构造器的结构体或基类,提供一个默认的构造器。下面我们在看一个例子。
class ShoppingList{
var name : String?
var quatity = 1
var purchased = false
}
这里ShoppingList
的所有属性都有默认值,它将自动获得一个可以为所有属性设置默认值的默认构造器。
1. 结构体的逐一成员构造器
如果结构体对所有存储型属性提供了默认值并且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。看一下下面的简单例子。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let size = Size(width: 2.0, height: 2.0)
}
}
struct Size {
var width = 0.0, height = 0.0
}
下面,Size
是一个结构体,它包含两个属性width
和height
,结构体自动获得一个逐一成员构造器init(width:height)
,可以为Size
创建新的实例。
值类型的构造器代理
构造器可以通过调用其他构造器来完成实例的部分构造过程,这一过程成为构造器代理,它能减少多个构造器间的代码重复。
构造器代理的实现规则和形式在值类型和类类型中有所不同,值类型(结构体和枚举)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给本身提供的其他构造器,类则不同,它可以继承自其他类,这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。
对于值类型,你可以使用self.init
在自定义的构造器中引用其他的属于相同值类型的构造器,并且你只能在构造器内部使用self.init
在。
注意:如果你为某个值类型定义了一个定制构造器,你将无法访问到默认构造器(如果是结构体,则无法访问注意对象构造器),防止定义了定制的构造器,别人还是错误的使用自动生成的构造器。
下面看一个例子。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init() {
}
init(origin : Point, size : Size) {
self.origin = origin
self.size = size
}
init(center : Point, size : Size) {
let originX = center.x - size.width * 0.5
let originY = center.y - size.height * 0.5
self.init(origin: Point(x : originX, y : originY), size: size)
}
}
这里用到了三个构造器,如下:
- 第一个构造器
init()
,在功能上根没有自定义构造器时自动获得的默认构造器是一样的,大括号里什么都没做,调用这个构造器就会返回一个Rect
实例,它的origin
和size
属性都使用自定义的默认值Point
(x = 0.0, y = 0.0)和Size (width = 0.0, height = 0.0)
。
下面我们调用一下
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let basicRect = Rect()
print(basicRect.origin)
print(basicRect.size)
}
}
下面看输出结果
Point(x: 0.0, y: 0.0)
Size(width: 0.0, height: 0.0)
- 第二个
Rect
构造器init(origin : size : )
,在功能上跟结构体在没有自定义构造器时获得的逐一成员构造器是一样的,这个构造器只是简单的将origin
和size
参数值赋值给对应的存储型属性。
下面我们调用一下。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let originRect = Rect(origin: Point(x : 2.0, y : 2.0), size : Size(width: 5.0, height: 5.0))
print(originRect.origin)
print(originRect.size)
}
}
下面看输出结果
Point(x: 2.0, y: 2.0)
Size(width: 5.0, height: 5.0)
- 第三个
Rect
构造器init(center : size :)
,这个复杂一点,先通过center
和size
计算origin
坐标,然后调用或代理给init(origin : size : )
构造器构造出新的origin
和size
。
下面我们调用一下。
class JJPracticeVC: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let centerRect = Rect(center: Point(x : 4.0, y : 4.0), size: Size(width: 3.0, height: 3.0))
print(centerRect.origin)
print(centerRect.size)
}
}
下面看一下输出结果
Point(x: 2.5, y: 2.5)
Size(width: 3.0, height: 3.0)
后记
未完,待续~~~