阅读更多

0顶
0踩

移动开发

转载新闻 Swift的初始化方法

2015-01-08 14:51 by 正式编辑 cao345657340 评论(0) 有3603人浏览
摘要:Swift有着超级严格的初始化方法,不仅强化了designated初始化方法的地位,所有不加修饰的init方法都需要在方法中确保非Optional的实例变量被赋值初始化,

而在子类中,也强制调用super版本的designated初始化。
我们在深入初始化方法之前,不妨先再想想Swift中的初始化想要达到一种怎样的目的。

其实就是安全。在Objective-C中,init方法是非常不安全的:没有人能保证init只被调用一次,也没有人保证在初始化方法调用以后,实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的话,还可能会造成各种问题。虽然Apple也明确说明了不应该在init中使用属性来访问,但这并不是编译器强制的,因此还是会有很多开发者犯这样的错误。

所以Swift有了超级严格的初始化方法。一方面,Swift强化了designated初始化方法的地位。Swift中不加修饰的init方法都需要在方法中保证所有非Optional的实例变量被赋值初始化,而在子类中也强制 (显式或隐式地)调用super版本的designated初始化,所以无论如何走何种路径,被初始化的对象总是可以完成完整的初始化的。
class ClassA {  
    let numA: Int  
    init(num: Int) {  
        numA = num  
    }  
}  
class ClassB: ClassA {  
    let numB: Int  
  
    override init(num: Int) {  
        numB = num + 1  
        super.init(num: num)  
    }  
}  

在上面的示例代码中,注意在init里我们可以对let的实例常量进行赋值,这是初始化方法的重要特点。在Swift中let声明的值是不变量,无法被写入赋值,这对于构建线程安全的API十分有用。而因为Swift的init只可能被调用一次,因此在init中我们可以为不变量进行赋值,而不会引起任何线程安全的问题。

与designated初始化方法对应的是在init前加上convenience关键字的初始化方法。这类方法是Swift初始化方法中的“二等公民”,只作为补充和提供使用上的方便。所有的convenience初始化方法都必须调用同一个类中的designated初始化完成设置,另外convenience的初始化方法是不能被子类重写或从子类中以super的方式被调用的。
class ClassA {  
    let numA: Int  
    init(num: Int) {  
        numA = num  
    }  
    convenience init(bigNum: Bool) {  
        self.init(num: bigNum ? 10000 : 1)  
    }  
}  
class ClassB: ClassA {  
    let numB: Int  
    override init(num: Int) {  
        numB = num + 1  
        super.init(num: num)  
    }  
}  

只要在子类中实现重写了父类convenience方法所需要的init方法的话,我们在子类中就也可以使用父类的convenience初始化方法了。比如在上面的代码中,我们在ClassB里实现了init(num: Int)的重写。这样,即使在ClassB中没有bigNum版本的convenience init(bigNum: Bool),我们仍然还是可以用这个方法来完成子类初始化:
let anObj = ClassB(bigNum: true)  
// anObj.numA = 10000, anObj.numB = 10001 

因此进行一下总结,可以看到初始化方法永远遵循以下两个原则:

  1. 初始化路径必须保证对象完全初始化,这可以通过调用本类型的designated初始化方法来得到保证;
  2. 子类的designated初始化方法必须调用父类的designated方法,以保证父类也完成初始化。
对于某些我们希望子类中一定实现的designated初始化方法,我们可以通过添加required关键字进行限制,强制子类对这个方法重写实现。这样的一个最大的好处是可以保证依赖于某个designated初始化方法的convenience一直可以被使用。一个现成的例子就是上面的init(bigNum: Bool):如果我们希望这个初始化方法对于子类一定可用,那么应当将init(num: Int)声明为必须,这样我们在子类中调用init(bigNum: Bool)时就始终能够找到一条完全初始化的路径了:
class ClassA {  
    let numA: Int  
    required init(num: Int) {  
        numA = num  
    }  
    convenience init(bigNum: Bool) {  
        self.init(num: bigNum ? 10000 : 1)  
    }  
}  
class ClassB: ClassA {  
    let numB: Int  
    required init(num: Int) {  
        numB = num + 1  
        super.init(num: num)  
    }  
}  

另外需要说明的是,其实不仅仅是对designated初始化方法,对于convenience的初始化方法,我们也可以加上required以确保子类对其进行实现。这在要求子类不直接使用父类中的convenience初始化方法时会非常有帮助。

作者:王巍(@onevcat),iOS和Unity3D开发者。
来自: SWIFTER
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Swift中初始化方法的顺序介绍

    主要介绍了Swift中初始化方法的顺序介绍,本文介绍的是了类的初始化方法,需要的朋友可以参考下

  • Swift中初始化init的方法小结

    Swift有着超级严格的初始化方法,不仅强化了designated初始化方法的地位,所有不加修饰的init方法都需要在方法中确保非Optional的实例变量被赋值初始化,下面这篇文章主要给大家介绍了关于Swift中初始化init的相关...

  • Swift初始化方法

    Swift中有两类初始化方法:designated(指定)和convenience(便利)初始化方法。convenience初始化方法必须调用同一个类(self)中的designated初始化。 designated构造器: init(parameters){ } convenience构造器 ...

  • Swift初始化(Initialization)

    一个类、结构体或枚举能定义一个初始化方法来设置它的特性,用来确保它的所有属性都是有效的初始值。通过调用类、结构或枚举提供的初始化方法可以执行实例的初始化过程。 构造初始化类、结构体和枚举的初始化方法所...

  • Swift初始化方法顺序

    2.调用父类的相应的初始化方法; 3.对父类中的需要改变的成员进行设定。 例如: class Cat {  var name:String  init() {  name = "cat"  } } class Tiger:Cat {  l

  • Swift-属性、方法(继承、重写)、初始化

    Swift中跟市里相关的属性可以分为2大类 存储属性(Strored Property) 类似于成员变量的概念,存储在实例的内存中,结构体、类可以定义存储属性,枚举不可以定义存储属性

  • 简化 Swift 字体初始化方法.zip

    简化 Swift 字体初始化方法.zip,Font management (System & Custom) for iOS and tvOS

  • ios swift5 自定义初始化方法 convenience init UIViewController

    var troubleStrArr:[String] = [] convenience init(troubleStrArr:[String]){ self.init(nibName: nil, bundle: nil) self.troubleStrArr = troubleStrArr }

  • Swift中类的初始化和反初始化

    1.初始化器在创建特定类型的实例时被调用 var focus = Fahrenheit() struct Fahrenheit { var temperature: Double init() { temperature = 32.0 } } 2.默认的属性值 如上所述,你可以在初始化器里为...

  • Swift 类、结构体的初始化

    1、初始化器 初始化器在创建特定类型的实例时被...Swift 为所有没有提供初始化器的结构体或类提供了一个默认的初始化器来给所有的属性提供 了默认值。这个默认的初始化器只是简单地创建了一个所有属性都有默认值的新

  • Swift初始化方法返回NIL

    在 Objective-C 中,init 方法除了返回 self 以外,其实和一个普通的...但是,在 Swift 中默认情况下初始化方法是不能写 return 语句来返回值的,也就是说我们没有机会初始化一个 Optional 的值。我们可以在 init 声

  • Swift 指定初始化器和便捷初始化器

    用与值类型的简单初始化器相同的方式来写类的指定初始化器 用 convenience 修饰符放到 init 关键字前定义便捷初始化器 //类的初始化器 class Person { var name: String var age: Int //指定初始化器 init(name...

  • Swift - 初始化方法顺序

    与Objective-C不同,Swift的初始化方法需要保证类型的所有属性都被初始化,所以初始化方法的调用顺序就很有讲究。在某个类的子类中,初始化方法里语句的顺序并不是随意的,我们需要保证在当前子类实例的成员初始化...

  • Swift编程中的初始化与反初始化完全讲解

    主要介绍了Swift编程中的初始化与反初始化完全讲解,是Swift入门学习中的基础知识,需要的朋友可以参考下

  • Swift中defer的正确使用方法

    准备把 swift 文档再扫一遍,发现了defer这个关键字,所以下面这篇文章主要给大家介绍了关于Swift中defer的正确使用方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  • Swift基础 类的初始化方法-构造函数

    类的初始化 类的初始化是调用init()方法进行的,在 Objective-C 中,init()方法是不...一方面,Swift 强化了 designated 初始化方法的地位。Swift 中不加修饰的 init 方法都需要在方法中保证所有非 Optional 的实例变

  • iOS swift5.5 Initialization 初始化方法

    文章目录 1.苹果官网文档 swift 2.参考博客 oc 1.苹果官网文档 swift Class Inheritance and Initialization - apple developer 2.参考博客 oc iOS: Designated Initializer(指定初始化函数)

  • Swift初始化相关内容

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

  • swift-Swift初始化语法糖用更简洁的语法实现组件初始化

    Swift 初始化语法糖,用更简洁的语法实现组件初始化

Global site tag (gtag.js) - Google Analytics