首页 文章

Swift:在类中实现协议初始化器

提问于
浏览
2

我试图理解为什么Swift强制执行符合协议的类,并将初始化程序标记为必需 . 这实质上强制任何子类也实现该初始化器 . 当然,指定的超类初始化程序将被继承?

以下引用来自Swift语言指南:https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID272

您可以将符合类的协议初始化程序要求实现为指定的初始值设定项或便捷初始值设定项 . 在这两种情况下,您必须使用required修饰符标记初始化程序实现:

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}

class SomeSubclass: SomeClass {
    required init(someParameter: Int) { // enforced to implement init again
        // initializer implementation goes here
    }
}

使用required修饰符可确保在符合类的所有子类上提供初始化程序需求的显式或继承实现,以便它们也符合协议 .

EDIT: 我最初没有提到我目前仅限于Swift 2.1 . 它似乎是此版本中的编译器问题,并且在更高版本中不会发生 .

2 回答

  • 3

    当然,指定的超类初始化程序会被继承吗?

    不,不总是 . 如果子类定义了自己的指定初始化器,那么它将不会自动继承超类的指定初始化器 . 请考虑以下示例:

    class Foo {
        init() {}
    }
    
    class Bar : Foo {
    
        var str: String
    
        init(str: String) {
            self.str = str
        }
    }
    
    let b = Bar() // illegal – what value would the 'str' property have?
    

    由于 Bar 定义了自己的 init(str:) 指定初始化程序,因此它不会自动继承 Foo 的指定初始化程序 init() . 这可以防止在子类声明其自己的存储属性的情况下进行不安全的初始化 .

    init() 标记为 required 强制 Bar 具有 init() ,无论是通过提供自己的实现:

    class Foo {
        required init() {}
    }
    
    class Bar : Foo {
    
        var str: String
    
        init(str: String) {
            self.str = str
        }
    
        // implement required init(), as Bar defines its own designated initialiser.
        required init() {
            self.str = "foo" // now str is correctly initialised when calling init()
        }
    }
    
    let b = Bar() // now legal
    

    或者通过继承 Foo 的实现(当 Bar 没有定义自己的指定初始化器时):

    class Foo {
        required init() {}
    }
    
    class Bar : Foo {
        // inherits init() from Foo, as Bar doesn't define its own designed initialisers.
    }
    
    let b = Bar() // legal
    
  • 2

    您没有强制在子类中实现初始化程序 . 考虑这个例子,编译得很好:

    protocol SomeProtocol {
        init(someParameter: Int)
    }
    
    
    class SomeClass: SomeProtocol {
        required init(someParameter: Int) {
            // initializer implementation goes here
            print(someParameter)
        }
    }
    
    
    class SomeSubclass: SomeClass {
        // Notice that no inits are implemented here
    }
    
    _ = SomeClass(someParameter: 123)
    _ = SomeSubclass(someParameter: 456)
    

相关问题