热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Swift初始化方法的使用介绍

目录初始化初始化器初始化器的相互调用两段式初始化安全检查重写自动继承初始化初始化器1、类、结构体、枚举都可以定义初始化器classSize{init(age:Int){}}vars

初始化

初始化器

1、类、结构体、枚举都可以定义初始化器

class Size {
    init(age: Int) {
    }
}
var s = Size(age: 10)

2、类有2种初始化器:指定初始化器(deaignated initializer)、便捷初始化器(convenience initializer)

class Size {
    //指定初始化器
    init(age: Int) {
    }
    //便捷初始化器
    convenience init(age: Int) {
    }
}

3、每个类至少有一个指定初始化器,指定初始化器是类的主要初始化器

4、默认初始化器总是类的指定初始化器

5、类偏向于少量指定初始化器,一个类通常只有一个指定初始化器

6、初始化器的相互调用规则,会更安全

指定初始化器必须从它的直系父类调用指定初始化器;

class Person {
    var age: Int
    init(age: Int) {
        self.age = age
    }
    convenience init() {
        self.init(age: 0)
    }
}
class Student: Person {
    var score: Int
    init(age: Int, score: Int) {
        self.score = score
        super.init(age: age)
    }
}

便捷初始化器必须从相同的类里调用另一个初始化器;

便捷初始化器最终必须调用一个指定初始化器;

class Size {
    var width: Int
    var height: Int
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
    convenience init(width: Int) {
        self.init(width: width, height: 0)
    }
    convenience init(height: Int) {
        self.init(width: 0, height: height)
    }
    convenience init() {
        self.init(width: 0, height: 0)
    }
}
var s1 = Size(width: 10, height: 20)
var s2 = Size(width: 10)
var s3 = Size(height: 20)
var s4 = Size()

初始化器的相互调用

Swift初始化方法的使用介绍

两段式初始化

1、Swift在编码安全方面是煞费苦心,为了保证初始化过程的安全,设定了两段式初始化、安全检查。

2、两段式初始化,第1阶段:初始化所有存储属性

  1. 外层调用指定\便捷初始化器
  2. 分配内存给实例,但未初始化
  3. 指定初始化器确保当前类定义的存储属性都初始化
  4. 指定初始化器调用父类的初始化器,不断向上调用,形成初始化器链

3、两段式初始化,第2阶段:设置新的存储属性值

从顶部初始化器往下,链中的每一个指定初始化器都有机会进一步定制实例

初始化器现在能够使用self(访问、修改它的属性,调用它的实例方法等等)

最终,链中任何便捷初始化器都有机会定制实例以及使用self

class Person {
    var age: Int
    init(age: Int) {
        self.age = age
        self.test()
    }
    func test() {
    }
}
class Student: Person {
    var score: Int
    init(age: Int, score: Int) {
        self.score = score
        super.init(age: age)
    }
    convenience init() {
        self.init(age: 0, score: 0)
    }
}

安全检查

1、指定初始化器必须保证在调用父类初始化器之前,其所在类定义的所有存储属性都要初始化完成

2、指定初始化器必须先调用父类初始化器,然后才能为继承的属性设置新值

3、便捷初始化器必须先调用同类中的其他初始化器,然后再为任意属性设置新值

4、初始化器在第1阶段初始化完成之前,不能调用任何实例方法,不能读取任何实例属性的值,也不能引用self

重写

1、当重写父类的指定初始化器时,必须加上override(即使子类的实现是便捷初始化器)

2、如果子类写了一个匹配父类便捷初始化器的初始化器,不用加上override

因为父类的便捷初始化器永远不会通过子类直接调用,因此,严格来说,子类无法无法重写

父类的便捷初始化器。

class Person {
    var age: Int
    init(age: Int) {
        self.age = age
    }
    convenience init() {
        self.init(age: 0)
    }
}
class Student: Person {
    var score: Int
    init(age: Int, score: Int) {
        self.score = score
        super.init(age: age)
    }
    init() {
        self.score = 0
        super.init(age: 0)
    }
}

自动继承

1、如果子类没有自定义任何指定初始化器,他会自动继承父类所有的指定初始化器

2、如果子类提供了父类所有指定初始化器的实现(要么通过方式1继承,要么重写)

子类会自动继承所有的父类便捷初始化器

3、就算子类添加了更多的便捷初始化器,这些规则仍然适用

class Person {
    var age: Int
    var name: String
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
    init() {
        self.age = 0
        self.name = ""
    }
    convenience init(age: Int) {
        self.init(age: age, name: "")
    }
    convenience init(name: String) {
        self.init(age: 0, name: name)
    }
}
class Student: Person {
    var no: Int = 0
    convenience init(no: Int) {
        self.init()
    }
}
原文地址:https://blog.csdn.net/run_in_road/article/details/125654292

推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • imnewtotheswiftandxcodeworld,soimhavingaproblemtryingtointegrateapackagetomypro ... [详细]
  • java.lang.Class.getDeclaredMethod()方法java.lang.Class.getDeclaredMethod()方法用法实例教程-方法返回一个Met ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
author-avatar
低调酥紫_631
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有