Swift---14-15.构造过程,析构过程

本文参考内容:Swift 3.0更新说明

构造过程与析构过程,类似与OC中的allocdealloc,一生成一释放,所以放在一起写


  • 构造过程

    • 属性默认值:

我们定义类的属性时,必须为每个属性设置默认值,否则会报错,可选类型的属性,若我们不进行赋值,也有一个默认值nil
class SomeClass { var num = 0 }
- ####构造器:
Swift中,类,结构体或者枚举提供了构造方法init,每当实例化对象时,都会默认调用此方法
class SomeClass { var num:Int init() { num = 3 print("init") } } var someClass = SomeClass()
- ####自定义构造器:
Swift中,我们可以通过修改init方法中的传入参数,达到自定义构造器的效果.注意传入参数必须拥有标签名来区分对应的init方法,同样你也可以使用关键字_来忽略传入参数名称.
class SomeClass { var num:Int init(num:Int) { self.num = num print("init") } init(_ num:Int) { self.num = num } } var someClass = SomeClass(num: 3) var anotherClass = SomeClass(3)
- 如果类的属性为不为可选类型,如果未在"init"方法中对属性进行赋值,且在定义属性时也没有赋予默认值.可选类型之所以不报错,是因为它有一个默认值nil
class SomeClass { var num:Int var numPlusThree:Int? init(num:Int) { self.num = num print("init") } func plus() -> Int { numPlusThree = num + 3 return numPlusThree! } } var someClass = SomeClass(num: 3) someClass.plus()
- ####默认构造器:
Swift中,如果结构体或类都有默认值,则编译器会隐式的增添一个构造器为所有属性设置默认值.若结构体中没有为属性设置默认值,我们可以在生成实例时使用它的逐一成员构造器
//定义一个拥有默认值的结构体,使用默认构造器生成实例 struct SomeStruct { var a:Int = 1 var b:Int = 2 } var someStruct = SomeStruct() //定义一个拥有默认值的结构体,使用逐一构造器生成实例 struct AnotherStruct { var a:Int var b:Int } var anotherStruct = AnotherStruct(a: 2, b: 3) //定义一个拥有默认值的类,使用默认构造器生成实例 class SomeClass { var a = 1 var b = 2 } var someClass = SomeClass()
- ####可失败构造器:
Swift中,提供了一种可以构造失败的构造器.
- 当构造器传入无效参数,或者缺少某种外部资源,或者不满足某个条件等,我们可失败构造器中返回"nil"对象来代替实例,但当成功的时候,我们不能返回任何东西
- 使用init?来创建可失败构造器,注意,可失败构造器与普通构造器的传入参数不可相同
- 我们可以重写可失败构造器,并把他改成普通构造器.但我们不能通过重写,把普通构造器改成可失败构造器
class NumberGreatterThanZero { var number:Int init() {} init?(num:Int) { if num <= 0 { return nil } else { number = num } } } class SubNumber : NumberGreatterThanZero{ override init(num:Int) { super.init() if num < 1 { number = 0 }else { number = num } } } var superNum = NumberGreatterThanZero(num:0)//返回nil var subNum = SubNumber(num:0)//返回实例 var number = NumberGreatterThanZero(num: 0) if number == nil { print("init fail") }
- ####必要构造器:
Swift中,在父类的构造器方法前添加required关键字,来强制要求所有的子类必须实现该构造器
class SomeClass { var name:String required init() { name = "name" } } class SomeSubclass: SomeClass { required init() { super.init() name = "subName" } }
- 枚举中,自动拥有init?(rawValue)的隐藏可失败构造器,前提是该枚举必须设置了原始值
enum Number:Int { case one = 1 case two,three,four } var one = Number(rawValue: 1) var five = Number(rawValue: 5)
- ####构造器代理:
Swift中,构造器可以通过调用其它构造器来完成实例的部分构造过程,这一过程称为结构器代理.在构造器中,使用self.init可以调起其他构造器方法
struct AnotherStruct { var a:Int var b:Int init(a:Int,b:Int) { self.a = a self.b = b } init (num:Int) { self.init(a:num,b:num+3) } } var anotherStruct = AnotherStruct(num: 3) print(anotherStruct.a,anotherStruct.b)

  • 类的继承和构造过程

    • 指定构造器和便利构造器
      • 指定构造器:

Swift中,指定构造器是类中最主要的构造器,一个指定构造器将初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化。置顶构造器的写法与上述的方法相同
init(parameters) { statements }
- #####便利构造器:
Swift中,便利构造器是次要的构造器,一般用来调起同类中的某个指定构造器,或者创建某个特殊的实例.使用关键字convenience
convenience init(parameters) { statements }
- #####类的构造器代理规则
- 指定构造器必须调用其直接父类的指定构造器
- 便利构造器只能调用同类中的构造器,且最终必须调起一个指定构造器.
- ####两段式构造过程:
Swift中,类的构造过程包含两个阶段。第一个阶段,每个存储型属性被引入它们的类指定一个初始值。当每个存储型属性的初始值被确定后,第二阶段开始,它给每个类一次机会,在新实例准备使用之前进一步定制它们的存储型属性。
- #####阶段 1
- 某个指定构造器或便利构造器被调用。
- 完成新实例内存的分配,但此时内存还没有被初始化。
- 指定构造器确保其所在类引入的所有存储型属性都已赋初值。存储型属性所属的内存完成初始化。
- 指定构造器将调用父类的构造器,完成父类属性的初始化。
- 这个调用父类构造器的过程沿着构造器链一直往上执行,直到到达构造器链的最顶部。
- 当到达了构造器链最顶部,且已确保所有实例包含的存储型属性都已经赋值,这个实例的内存被认为已经完全初始化。此时阶段 1 完成。
- #####阶段 2
- 从顶部构造器链一直往下,每个构造器链中类的指定构造器都有机会进一步定制实例。构造器此时可以访问self、修改它的属性并调用实例方法等等。
- 最终,任意构造器链中的便利构造器可以有机会定制实例和使用self。
- ####构造器的继承与重写:
Swift中,子类可以重写父类的指定构造器,使用override关键字,Swift中,当添加了该关键字,Swift会自动检查该类父类是否有对应的指定构造器,并验证参数.
注意,调用前需要确定子类中的所有属性必须有初始值
从上述的构造代理规则,以及两段式构造过程可以看出,子类重写父类的指定构造器时,须等待父类完成构造.
此时才能对子类中的属性进行操作,方法进行调用.所以,我们在下面列子中,必须先调用super.init().

```
class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "\(numberOfWheels) wheel(s)"
    }
}
class Bicycle: Vehicle {
    var number : Int
    override init() {
        number = 0
        super.init()
        numberOfWheels = 2
    }
}
```
    - 构造器的自动继承
        - 规则 1
        如果子类没有定义任何指定构造器,它将自动继承所有父类的指定构造器。
        - 规则 2
        如果子类提供了所有父类指定构造器的实现——无论是通过规则 1 继承过来的,还是提供了自定义实现——它将自动继承所有父类的便利构造器。
  • 析构过程:

Swift中,生成实例时会有对应的构造器,那么对象释放时,也有对应的析构器,每个类只有一个析构器,deinit方法,该方法无法被主动调用,只有在对象释放时自动调用

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

推荐阅读更多精彩内容