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 i
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)
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