用返回非可选值的计算属性覆盖返回可选值的计算属性
Posted
技术标签:
【中文标题】用返回非可选值的计算属性覆盖返回可选值的计算属性【英文标题】:Overriding a computed property that returns an Optional value with one that returns a non-Optional 【发布时间】:2018-06-30 19:43:16 【问题描述】:在我运行 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
关键字才能编译代码。这已在 Playground 和适当的项目上进行了测试。
这是预期的行为吗?如果是,Apple 的文档中是否有针对这种情况的相关页面?
【问题讨论】:
您发现了一个有趣的发现。我认为这很有意义,因为每当您使用父类型时,您都期望非 nil 或 nil,这是由始终提供非 nil 的子类型来实现的。它不会以相反的方式工作(在父级中是非可选的,在子级中是可选的)。在某种程度上,这让我想起了 Liskov 替换原则(它更关注语义而不是语法,但仍然适用于 IMO)。我没有发现语言指南中明确提到了这种“现象”,但我希望 Swift 专业人士能过来并指出我们正确的页面:) @dr_barto 这个问题是当访问ChildThatUnwraps
的实例时,您不会解开computedOptional
,而如果您确实必须执行解开将对象转换为 ParentWithComputedOptional
- 即使它是同一个属性。
我的错,你当然是对的。这让它变得更有趣......
哦。它不仅适用于computed properties
,也适用于functions
。
【参考方案1】:
官方语言指南中似乎没有记录这种特殊的覆盖情况,但在 Swift 的 changelog 中提到了 4.0 版本(查找 SR-1529)。
这个主题值得一些额外的信息:
实际上,此行为不仅限于可选项,还适用于其他covariant 类型,只要被覆盖的属性是派生类中的计算只读属性。 例如,以下代码也将在 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 substitution principle 的极端情况,因为基类的属性是只读的计算属性。因此,如果Bar
的实例被保存在Foo
类型的变量中,则无法改变其x
属性,以便在将对象向下转换为Bar
类型的变量。
【讨论】:
以上是关于用返回非可选值的计算属性覆盖返回可选值的计算属性的主要内容,如果未能解决你的问题,请参考以下文章
Swift:XCTest 会修改状态吗?可以返回可选值的测试函数的约定是啥?