以下内容在运行 Swift 4 的 Xcode 9.2 上编译和运行没有问题:
class ParentWithComputedOptional {
var computedOptional: Int? { return nil }
}
class ChildThatUnwraps: ParentWithComputedOptional {
override var computedOptional: Int { return 10 }
}
请注意,在父级中,computedOptional
是Int?
,但在子项中,它被覆盖为Int
。此外,必须指定 override
关键字才能编译代码。这在操场和适当的项目上都进行了测试。
这是预期行为吗?如果是,Apple 文档中是否有适用于此方案的相关页面?
这种特殊的覆盖情况似乎没有记录在官方语言指南的任何地方,但在 Swift 的 4.0 版本更新日志中提到了(寻找 SR-1529(。
本主题需要一些其他信息:
实际上,此行为不仅限于可选,也适用于其他协变类型,只要重写的属性是派生类中的计算只读属性即可。例如,以下代码也将在 Swift 4.1 中进行编译。
class Animal {}
class Koala: Animal {}
class Foo {
var x: Animal { return Animal() }
}
class Bar: Foo {
override var x: Koala { return Koala() }
}
这是一个不违反 Liskov 替换原则的边缘情况,因为 Base 类的属性是只读计算的。因此,如果Bar
的实例保存在类型为 Foo
的变量中,则无法改变其 x
属性,以便在将对象向下转换为 Bar
类型的变量时创建类型错误。