Swift: Implementing Protocol Initializer in a Class

依然范特西╮ 提交于 2019-12-02 05:02:00

问题


I am trying to understand why Swift enforces a class that conforms to a protocol with an initializer to be marked as required. This essentially enforces any subclasses to also implement that initializer. Surely the designated superclass initializer would be inherited?

The quotes below are taken from the Swift Language Guide: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID272

You can implement a protocol initializer requirement on a conforming class as either a designated initializer or a convenience initializer. In both cases, you must mark the initializer implementation with the required modifier:

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
    }
}

The use of the required modifier ensures that you provide an explicit or inherited implementation of the initializer requirement on all subclasses of the conforming class, such that they also conform to the protocol.

EDIT: I had not initially mentioned that I am currently limited to Swift 2.1. It appears to be a compiler issue in this release and does not occur in later versions.


回答1:


Surely the designated superclass initializer would be inherited?

No, not always. If the subclass defines its own designated initialisers, then it won't automatically inherit the superclass' designated initialisers. Consider the following example:

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?

As Bar defines its own init(str:) designated initialiser, it doesn't automatically inherit Foo's designated initialiser init(). This prevents unsafe initialisation in cases where the subclass declares its own stored properties.

Marking init() as required enforces Bar has an init(), be it through providing its own implementation:

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

Or by inheriting Foo's implementation (when Bar doesn't define its own designated initialisers):

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:


You're not force to implement the initializer in the subclass. Consider this example, which compiles just fine:

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)


来源:https://stackoverflow.com/questions/42397348/swift-implementing-protocol-initializer-in-a-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!