【问题标题】:Designation & Convenience Initializer指定和便利初始化器
【发布时间】:2017-01-03 18:48:29
【问题描述】:

我对 swift 中的初始化程序有疑问。根据 Apples 的Swift3.0

  1. 指定初始化程序必须从其直接超类调用指定初始化程序。
  2. 便利构造器必须调用同一个类的另一个构造器。
  3. 便利构造器最终必须调用指定构造器。

现在我有两个 A 类和 B 类(A 的子类)。 A & B 都有两个具有以下结构的指定初始化器

谁能建议 B 类的指定初始化程序如何调用 A 类的初始化程序?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    由于您在A 中有两个指定的初始值设定项,因此由于签名不同,它们是明确的,并且可以相互区分。这意味着您可以轻松地从子类B 调用A 的适当指定 初始化程序。例如,A as

    class A {
        var a: Int
    
        // designated "#1"
        init() {
            a = 0
        }
    
        // designated "#2"
        init(_ a: Int) {
            self.a = a
        }
    
        // convenience initializer for A
        convenience init(_ foo: String) {
            print(foo)
            self.init(42)
        }
    }
    

    我们有,例如

    class B: A {
        let b: Int
    
        // designated "sub#1"
        override init() {
            b = 42
            super.init() // use A's designated #1
        }
    
        // designated "sub#2"
        override init(_ a: Int) {
            b = 24
            super.init(a) // use A's designated #2
        }
    
        // non-overriding designated "#3"
        init(b: Int) {
            self.b = b
            super.init() // use A's designated #1
        }
    
        // convenience initializer for B
        convenience init(_ foo: String) {
            print(foo)
            self.init() // use B's designated #1
        }
            // you may only call designated initializers of the superclass
    }
    

    但是请注意,子类的初始化器可能只能调用其超类的指定初始化器the Language Guide - Initializers - Initializer Delegation for Class Types [emphasis mine] 中的规则 1 和 2 涵盖了这一点:

    类类型的初始化器委托

    为了简化指定和便利之间的关系 初始化器,Swift 应用以下三个规则进行委托 初始化器之间的调用:

    规则 1

    指定初始化器必须从它的 直接超类

    第 2 条

    便利构造器必须从同一个构造器调用另一个构造器 类

    第 3 条

    便利构造器最终必须调用指定的 初始化器。

    所以你不能从B的便利构造器中访问A的便利构造器,并且B的指定构造器自然必须按照上面的规则1只调用A的指定构造器。

    【讨论】:

    • 感谢您的回答。在 DOC 中,Apple 说“两个指定的初始化程序都必须从超类调用单个指定的初始化程序”。那么在上述情况下,“A”的哪个初始化程序会得到调用?
    • @Gagan_iOS 在语言指南的示例中,A 只有一个指定初始化器,因此B 的两个指定初始化器无法选择必须调用其父类的哪个指定初始化器,因为只有一个。 如果,另一方面,超类有几个指定的初始化器,(直接)子类的指定初始化器自然可以选择这两个调用中的任何一个。回想一下,指定的初始化程序完全初始化了类(“指定的初始化程序完全初始化了该类引入的所有属性......”)。
    • ... 这意味着,在上面的示例中,在A 的两个指定初始化程序中,从B 中的给定指定初始化程序获取调用的那个是具有来自B 的调用的匹配签名。由于我们在A 中有两个指定的初始化程序,我们知道它们必须有不同的签名(因此可以区分),否则我们会产生歧义并提示编译器错误。
    • @Gagan_iOS 乐于助人:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-18
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 2019-08-20
    相关资源
    最近更新 更多