【问题标题】:returning swift protocol associated type in multiple methods以多种方法返回 swift 协议关联类型
【发布时间】:2022-02-03 23:45:44
【问题描述】:

来自 java/kotlin 背景,我试图了解具有相关类型的 swift 协议。为什么下面的sn-p编译失败,报错:“Type ViewFactoryImpl does not conform to protocol ViewFactory”,怎么解决?

protocol ViewFactory  {
    associatedtype V: View
    func createSomeView() -> V
    func createAnotherView() -> V
}

class ViewFactoryImpl: ViewFactory {
    
    func createSomeView() ->  some View {
        return ViewA()
    }
    
    func createAnotherView() ->  some View {
        return ViewB()
    }
}

通过玩耍,我能够通过定义以下内容来编译

protocol ViewFactory  {
    associatedtype V1: View
    associatedtype V2: View
    func createSomeView() -> V1
    func createAnotherView() -> V2
}

我不明白这个问题。我认为关联类型是为整个协议定义的,可以在多种方法中使用。我错过了什么?

【问题讨论】:

    标签: swift protocols associated-types


    【解决方案1】:
    1. 每个associatedtype 指一种类型。
    2. ViewAViewB 不是同一类型。
    3. some 不会把它们都变成同一种类型。

    即使它们由相同的类型支持,您也不能使用多个不透明的返回类型来匹配单个关联类型。

    protocol ViewFactory  {
      associatedtype View: SwiftUI.View
      func createSomeView() -> View
      func createAnotherView() -> View
    }
    
    // Type 'ViewFactoryImpl' does not conform to protocol 'ViewFactory'
    class ViewFactoryImpl: ViewFactory {
      func createSomeView() -> some View {
        ViewA()
      }
    
      func createAnotherView() -> some View {
        ViewA()
      }
    }
    

    最接近的方法是使用类型别名。它带有语义含义,但不会掩盖底层类型。

    class ViewFactoryImpl: ViewFactory {
      typealias View = ViewA
    
      func createSomeView() -> View {
        ViewA()
      }
    
      func createAnotherView() -> View {
        ViewA()
      }
    }
    

    【讨论】:

      【解决方案2】:

      你想出的解决方案正是你所需要的

      如其他地方所述,您的第一个协议的主要问题是您强制执行 createSomeView() createAnotherView() 两者都返回相同的类型。虽然ViewA()ViewB() 都是V 的候选对象,但由于它们符合View,它们仍然是不同的类型,因此在给定对象中不能同时是V

      通过同时定义V1V2,您允许每个函数返回不同类型或相同类型,这都是可以接受的。通过使 V1V2 都需要 View 一致性,您允许 some View 语法

      【讨论】:

      • 非常感谢您的反应,尽管我对自己的意图还不够清楚。这背后的想法是为具有多个模块的大型应用程序提供解耦导航的解决方案。为每个目的地定义关联类型对我来说似乎有点矫枉过正。使用 AnyView 将有助于消除类型问题,但在性能方面可能代价高昂。也许这种情况下最好的解决方案是坚持使用 UIKit 进行导航。这样至少我可以在视图之外操作导航状态
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 2022-11-27
      • 1970-01-01
      相关资源
      最近更新 更多