Swfit convenience 介绍

Swift 定义了两种类初始化器类型,用来保证所有成员属性能够获得一个初始化值,即 designated initializersconvenience initializers

最重要的写在最前面

如果仅仅是用于override, 就使用指定构造器(designated initializer)
如果需要对父类的构造器进行扩展, 则使用便利构造器(convenience initializer)

convenience

在Apple的官方文档中的描述:

Convenience initializers are secondary, supporting initializers for a class.
便利构造器是对类初始化方法的补充
You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values.
便利构造器需要调用同一个类里面的指定构造器, 在其中初始化值
You can also define a convenience initializer to create an instance of that class for a specific use case or input value type.
可以定义便利构造器去创建类的实例对象

convenience的一般用法: 扩展类的构造函数

extension UIColor {
    
    //convenience:便利,使用convenience修饰的构造函数叫做便利构造函数
    // 便利构造函数通常用在对系统的类进行构造函数的扩充时使用。
    // 便利构造函数的特点:
    // 1、便利构造函数通常都是写在extension里面, 也可以写在class里面
    // 2、便利函数init前面需要加载convenience
    // 3、在便利构造函数中需要明确的调用self.init()
    
    convenience init(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat = 1) {
        self.init(red: r / 255, green: g / 255, blue: b / 255, alpha: a)
    }
}

designated

在Apple的官方文档中的描述:

Designated initializers are the primary initializers for a class.
指定构造器是一个类的主构造器(不同的初始化路径可能调用不同的 designated initializers)
A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.

指定构造器中实现所有属性的初始化, 需要调用合适的父类构造器完成初始化.

class Person_ {
    
    var name: String!
    var weight: Double
    
    // 定义指定构造器, 必须实现所有属性的初始化
    required init() {
        self.name = ""
        self.weight = 0.0
    }
    init(name: String) {
        self.name = name
        self.weight = 0.0
    }
    init(name: String, weight: Double) {
        self.name = name
        self.weight = 0.0
    }
    
    // 定义便利构造器
    convenience init(n name: String, w weight: Double) {
        // 便利构造器必须调用同类中的指定构造器, 方便属性的初始化
        self.init(name: name, weight: weight)
    }
    
    convenience init(showStr: String) {
        // 便利构造器若不调用同类中的指定构造器(随便哪一个), 就会报错
        // 因为同类中的属性没有初始化, 会影响使用, Swift这方面确实严格
        self.init(name: "")
        print(showStr)
    }
}

class Man_: Person_ {
    override init(name: String) {
        // 子类的指定构造器中必须调用父类的指定构造器
        super.init(name: name)
        self.name = name
        self.weight = 0
    }
    
    override init(name: String, weight: Double) {
        super.init(name: name, weight: weight)
        self.name = name
        self.weight = weight
    }
    
    // 定义指定构造器与父类的便利构造器一样, 这里不算重写
    convenience init(showStr: String) {
        self.init(name: "", weight: 0)
        print(showStr)
    }

   // 如果父类使用了required关键字, 则子类会被强制要求重写这个初始化方法.
    required init() {
        fatalError("init() has not been implemented")
    }
}

总结:

  • 在构造器完成初始化之前, 不能调用任何实例方法,或读取任何实例属性的值,self 本身也不能被引用.
  • 子类中 designated initializer 必须调用父类中对应的 designated initializer,以保证父类也能完成初始化.
super.init()
  • 子类如果没有定义任何 designated initializer,则默认继承所有父类的 designated initializerconvenience initializer.
  • 可以通过添加 required 关键字强制子类重写其实现,以保证依赖该方法的 convenience initializer 始终可以使用.
  • convenience initializer 必须调用自身类中的其他初始化方法,并且最终必须调用一个 designated initializer.
  • 如果一个子类中任意的构造器和父类的便利构造器一模一样, 不算重写, 创建对象的时候也只会显示子类定义的构造器.

Swift在初始化过程中定义了这么多规则, 归根到底是为了所有属性能被初始化, 不会因此而报错

参考自
从 Swift 初始化说起
Swift中构造器的继承和重写

你可能感兴趣的:(Swfit convenience 介绍)