Search code examples
swiftoverridingcomputed-properties

Overriding a computed property that returns an Optional value with one that returns a non-Optional


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?


Solution

  • 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.