【问题标题】:Access function protocol in generic class泛型类中的访问函数协议
【发布时间】:2020-06-01 02:40:34
【问题描述】:

我想访问协议中的函数,但是 XCode 投诉

实例成员“createColumns”不能用于类型“T”;你是否 意思是改用这种类型的值?

我做了什么:

创建协议:

protocol StorageModelDelegate {
   func createColumns(for tableBuilder: TableBuilder)
}

创建接收 StorageModelDelegate 的类泛型:

class SQLiteStorage<T: StorageModelDelegate> {
     func createTable(tableName: TableKey) -> Bool {
           let table = Table(tableName.rawValue)

           let query = table.create(ifNotExists: true) { (builder: TableBuilder) in
                T.createColumns(for: builder) // -> this is the error comes up.
           }
     }
}

创建实现 SQLiteStorage 的类:

final class InfoStorageModel {
    private let sqlite: SQLiteStorage = SQLiteStorage<Info>()
}

那么,如何修复 SQLiteStorage 类中的错误?

【问题讨论】:

    标签: ios swift xcode generics protocols


    【解决方案1】:

    你想调用静态方法而不是实例方法。

    为了修复,你应该添加实例参数:

    首先,使用弱 var 委托来防止循环保留。

    protocol StorageModelDelegate: class {
       func createColumns(for tableBuilder: TableBuilder)
    }
    
    final class SQLiteStorage<T: StorageModelDelegate> {
    weak var delegate: T?
         func createTable(tableName: TableKey) -> Bool {
               let table = Table(tableName.rawValue)
    
               let query = table.create(ifNotExists: true) { (builder: TableBuilder) in
                    delegate?.createColumns(for: builder)
               }
         }
    }
    

    或者使用静态协议方法:

    protocol StorageModelDelegate {
       static func createColumns(for tableBuilder: TableBuilder)
    }
    
    
    final class SQLiteStorage<T: StorageModelDelegate> {
    weak var delegate: T?
         func createTable(tableName: TableKey) -> Bool {
               let table = Table(tableName.rawValue)
    
               let query = table.create(ifNotExists: true) { (builder: TableBuilder) in
                    T.createColumns(for: builder)
               }
         }
    }
    

    【讨论】:

      【解决方案2】:

      错误表明您需要T实例,而不是类型 本身。

      所以你需要这样的东西:

      class SQLiteStorage<T: StorageModelDelegate> {
          var delegate:T
      
          init (delegate:T) {
            self.delegate = delegate
          }
      
          func createTable(tableName: TableKey) -> Bool {
                let table = Table(tableName.rawValue)
      
                let query = table.create(ifNotExists: true) { (builder: TableBuilder) in
                      self.delegate.createColumns(for: builder) // -> this is the error comes up.
                }
          }
      }
      

      【讨论】:

      • 我想我会选择@Vyacheslav 的解决方案,因为如果我使用你的答案,我需要在创建 SQLiteStorage 对象时传递委托参数。比如:let storage = SQLiteStorage&lt;Info&gt;(delegate: Info())
      猜你喜欢
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多