Swift / SwiftUI:为什么我不能覆盖返回一些 View 的方法?

Ger*_*tan 5 overriding swift swiftui

在下面的例子中

import SwiftUI

class AbstractOverride {
    open func configurationView() -> AnyView {
        if Features.TEST_VERSION {
            return AnyView(Text("override configurationView()"))
        } else {
            return AnyView(EmptyView())
        }
    }
    
    open func someConfigurationView() -> some View {
        if Features.TEST_VERSION {
            return AnyView(Text("override someConfigurationView()"))
        } else {
            return AnyView(EmptyView())
        }
    }

}

class SubclassOverride: AbstractOverride {
    override func configurationView() -> AnyView { // no compiler error
        return AnyView(Text("Test"))
    }

    override func someConfigurationView() -> some View { // compiler error "Method does not override any method from its superclass"
        return AnyView(Text("Test"))
    }
}
Run Code Online (Sandbox Code Playgroud)

compiler error "Method does not override any method from its superclass"override func someConfigurationView() -> some View.

没有返回编译器错误AnyView

有人能解释一下这里发生了什么吗?为什么 Swift 不能识别方法签名是相同的?

这是 iOS 13,Xcode 11.5

小智 4

语言设计规定程序员完全不可能静态地获得有关两个不透明类型的关系的信息,例如它们是否存在于类继承链中。

\n
var instanceOfType1: some ExpressibleByBooleanLiteral = true\n\nvar anotherInstanceOfType1 = instanceOfType1 as! Bool // "fine" \n\n// Cannot assign value of type \'some ExpressibleByBooleanLiteral\' to type \'Bool\'\nanotherInstanceOfType1 = instanceOfType1\n\nvar instanceOfType2: some ExpressibleByBooleanLiteral = instanceOfType1 // fine\ntype(of: instanceOfType1) == type(of: instanceOfType2) // true\n\n// Cannot assign value of type \'some ExpressibleByBooleanLiteral\' (type of \'instanceOfType1\')\n// to type \'some ExpressibleByBooleanLiteral\' (type of \'instanceOfType2\')\ninstanceOfType2 = instanceOfType1\n
Run Code Online (Sandbox Code Playgroud)\n

最初,在非最终声明中使用不透明类型是被禁止的。

\n
\n

不透明结果类型不能用于\na class\xe2\x80\xa6 中的非最终声明

\n
\n
\n

可以想象,这个限制将来可能会被取消,但这意味着重写实现将被限制为返回与其超级实现相同的类型,这意味着它们必须调用 super.method() 才能产生有效的返回值。

\n
\n

限制已解除,但目前无法使用。例如,即使是最简单的覆盖也无法编译。

\n
override func someConfigurationView() -> some View {\n  super.someConfigurationView()\n}\n
Run Code Online (Sandbox Code Playgroud)\n

不透明类型不能提供任何保护来防止违反SOLID中的“L”规则。实际上可能与(如您一样)相同或子类型,但语言无法强制执行这一点。some Viewsome ViewAnyViews

\n

\xe2\x80\xa6 例如,如果您不使用 来编写,则会违反合同AnyView,就像您应该做的那样:

\n
class AbstractOverride {\n  @ViewBuilder func someConfigurationView() -> some View {\n    if Features.TEST_VERSION {\n      Text("override someConfigurationView()")\n    }\n  }\n}\n\nfinal class SubclassOverride {\n  func someConfigurationView() -> some View {\n    Text("Test")\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

最不痛苦的解决方案是完全禁止自己在 Swift 中使用类继承。它从来就不是惯用的\xe2\x80\x94,它实际上只是用于与 Objective-C 交互。

\n
struct ContentView<\n  ConfigurationViewProvider: ModuleName.ConfigurationViewProvider\n>: View {\n  var body: some View {\n    ConfigurationViewProvider.someConfigurationView\n  }\n}\n\nstruct ContentView_Previews: PreviewProvider {\n  static var previews: some View {\n    ContentView<SubclassOverride>()\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
protocol ConfigurationViewProvider {\n  associatedtype ConfigurationView: View\n\n  @ViewBuilder static var someConfigurationView: ConfigurationView { get }\n}\n\nenum AbstractOverride: ConfigurationViewProvider {\n  static var someConfigurationView: some View {\n    if Features.TEST_VERSION {\n      Text("override someConfigurationView()")\n    }\n  }\n}\n\nenum SubclassOverride: ConfigurationViewProvider {\n  static var someConfigurationView: some View {\n    Text("Test")\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n