swift之构造过程

构造过程是使用类、结构体或枚举类型的实例之前的准备过程。包括设置实例中每个存储属性的初始值和执行其他必须的设置或构造过程。

一、构造器
构造器在创建某个特定类型的新实例时被调用。它的最简形式类似于一个不带任何形参的实例方法,以关键字 init 命名:

init() {
    // 在此处执行构造过程
}

二、存储属性的初始赋值
类和结构体在创建实例时,必须为所有存储型属性设置合适的初始值,存储型属性的值不能处于一个未知的状态。
1、可以在构造器中为存储型属性设置初始值;
2、也可以在定义属性时分配默认值。
如下定义了一个用来保存华氏温度的结构体 Fahrenheit,它拥有一个 Double 类型的存储型属性 temperature,如果不给temperature设置一个初始值的话,就会报错。

image.png

正确写法:

//在**构造器中**为存储型属性设置初始值
struct Fahrenheit {
   var temperature: Double
   init() {
       temperature = 20.0
   } 
 }

//通过在**属性声明**时为 temperature 提供默认值
struct Fahrenheit {
    var temperature = 32.0
}

三、自定义构造过程
1、自定义构造过程时,可以在定义中提供构造形参,指定其值的类型和名字

struct Person {
    var name: String = "King"
    init(fromFamilyName familyName:String) {
        name = name + " " + familyName
    }
}
let person = Person(fromFamilyName: "David")
print(person.name)
//King David

上面的构造器有一个构造形参,其实参标签为 fromFamilyName,形参命名为 familyName;

2、形参命名和实参标签

struct Color {
    let red: Double, green: Double, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
}

let color = Color(red: 1.0, green: 2.0, blue: 2.0)

Color 提供了一个构造器,为红蓝绿提供三个 Double 类型的形参命名red,green,blue,在创建实例的时候他们就是构造器的实例标签。使用时,创建Color实例的时候,必须用构造器的实参标签*,如果不通过实参标签传值,这个构造器是没法调用的。如果构造器定义了某个实参标签,就必须使用它。

let veryGreen = Color(0.0, 1.0, 0.0)
// 报编译期错误-需要实参标签

3、不带实参标签的构造器形参
如果你不希望在构造器中某个形参使用实参标签,可以使用下划线(_)来代替显式的实参标签来重写默认行为。

struct Color {
    let red: Double
    init(_ red: Double) {
        self.red   = red
    }
}
let color = Color(red: 1.0)
// 错误调用:  报错 Extraneous argument label 'red:' in call

let color = Color(1.0)
// 正确调用(用下划线的时候,实参标签red是不可以用的)

4、可选属性类型
如果你自定义的类型有一个逻辑上允许值为空的存储型属性——无论是因为它无法在初始化时赋值,还是因为它在之后某个时机可以赋值为空——都需要将它声明为 可选类型。可选类型的属性将自动初始化为 nil,表示这个属性是特意在构造过程设置为空。

struct Question {
    var reason :String
    var response: String?
    init(reason: String) {
        self.reason = reason
    }
}
//上面构造器里面只需要(并且必须要)初始化reason的值,不需要设置response的值,因为response的值是可选的,已经自动出海刷为nil了。

5、构造过程中常量属性的赋值
你可以在构造过程中的任意时间点给常量属性赋值,只要在构造过程结束时它设置成确定的值。一旦常量属性被赋值,它将永远不可更改。

class Question {
    let reason :String
    var response: String?
    init(reason: String) {
        self.reason = reason
    }
}

let question = Question(reason: "i love it") //只能在构造过程给常量属性reason赋值
question.reason = "么么哒" //常量属性reason的值不能被修改(报错:Cannot assign to property: 'reason' is a 'let' constant)
print(question.reason)
// 打印i love it

6.默认构造器
如果结构体或类为所有属性提供了默认值,又没有提供任何自定义的构造器,那么 Swift 会给这些结构体或类提供一个默认构造器。

class Question {
    let reason :String = "i love it"
    var response: String?
}
let question = Question()

由于 Question 类中的所有属性都有默认值,且它是没有父类的基类,它将自动获得一个将为所有属性设置默认值的并创建实例的默认构造器(由于 response 属性是可选 String 类型,它将接收一个默认 nil 的默认值,尽管代码中没有写出这个值)

6、结构体的逐一成员构造器
结构体如果没有定义任何自定义构造器,它们将自动获得一个逐一成员构造器。不像默认构造器,即使存储型属性没有默认值,结构体也能会获得逐一成员构造器。

struct Size {
    var width : Double
    var height: Double
}
let size = Size(width: 1.0, height: 2.0)

像上面的结构体size,可以省略构造器。如果属性都赋予初始值得话,在创建结构体实例的时候还可以如下:创建实例的时候省略属性,这时候自动分配的构造器会使用默认值

struct Size {
    var width  = 1.0
    var height = 2.0
}

let size = Size()

7、值类型的构造器代理
构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理,它能避免多个构造器间的代码重复。

struct Point {
    var x = 0.0
    var y = 0.0
}

struct Size {
    var width = 0.0
    var height = 0.0
}

struct Rect {
    var orgin = Point()
    var size  = Size()
    init() {
        
    }
    
    init(orgin:Point, size:Size) {
        self.orgin = orgin
        self.size  = size
    }
    
    init(center:Point, size:Size) {
        let orginX = center.x - size.width/2
        let orginY = center.y - size.height/2
        self.init(orgin: Point(x: orginX, y: orginY), size:size)
    }
}

let baseReact = Rect()
let orginReact = Rect(orgin: Point(x: 1.0, y: 2.0), size: Size(width: 1.0, height: 2.0))
let centerReact = Rect(center: Point(x: 1.0, y: 2.0), size: Size(width: 1.0, height: 2.0))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容