The following compiles and runs with no issue on my Xcode 9.2 running Swift 4:
class ParentWithComputedOptional {
var computedOptional: Int? { return nil }
}
class ChildThatUnwraps: ParentWithComputedOptional {
override var computedOptional: Int { return 10 }
}
Notice that in the parent, computedOptional
is an Int?
, but in the child it is overridden to be an Int
. Furthermore, the override
keyword has to be specified for the code to compile. This was tested on both Playground and a proper project.
Is this expected behaviour? If yes, is there a relevant page in Apple's documentation for this scenario?
Hi, Swift rules state that any inherited property can be overridden whether it is implemented as a stored or computed property at source (parent class).
Computed properties are part of a family of property types in Swift. Stored properties are the most common which save and return a stored value whereas computed ones are a bit different. A computed property, it's all in the name, computes its property upon request.
Swift Computed Property For example, class Calculator { // define stored property var num1: Int = 0 ... } Here, num1 is a stored property, which stores some value for an instance of Calculator . However, there is another type of property called computed properties.
Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value. Computed properties are provided by classes, structures, and enumerations. Stored properties are provided only by classes and structures.
This particular case of overriding doesn't appear to be documented anywhere in the official language guide, but is mentioned in Swift's changelog for the 4.0 release (look for SR-1529).
This topic deserve some additional information:
Actually, this behavior isn't limited to optionals, but also applies to other covariant types, as long as the overridden property is a computed read-only one in the derived class. For instance, the following code will compile as well in Swift 4.1.
class Animal {}
class Koala: Animal {}
class Foo {
var x: Animal { return Animal() }
}
class Bar: Foo {
override var x: Koala { return Koala() }
}
This is a edge case that doesn't violate the Liskov substitution principle, because the Base class' property is a read-only computed one. Hence, if an instance of Bar
were to be held in a variable of type Foo
, there'd be no way to mutate its x
property so that it'd create a type error when downcasting the object to a variable of type Bar
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With