Yep, pretty much. Same reason you cannot override a method that returns some type T with one that returns a T?.
Because if you could, then what happens if you do this:
class Base {
convenience init(x: Int) {
self.init(y: x)
print(self)
}
init(y: Int) {}
}
class Sub: Base {
override init?(y: Int) { return nil }
}
Sub(x: 0) // what does this print?
The superclass’s initializer defines a contract for what callers can expect.
A non‑failable init promises to always produce an instance; a failable init? only promises to maybe produce one.
When overriding, you’re allowed to strengthen this contract but not weaken it.
Overriding a failable initializer with a non‑failable one is fine: callers that are prepared for nil still work if they never actually get nil.
But overriding a non‑failable initializer with a failable one would break the contract, because callers relying on a guaranteed instance could suddenly receive nil.
(full disclosure: I used AI to help clarify my text in this post )
You can also think of a call to an initializer as being pretty much the same as calling a static method that either returns Self, or Self? (if it’s failable). A similar rule is enforced for method overrides, where you can override a method returning T? with one returning T but not vice versa.
Overriding a property works the same if the property is read only. If it has a setter, the override is required to have the same exact type.