簡體   English   中英

如何在Swift 3中調用具有相關類型參數的泛型函數

[英]How to call a generic function with parameter of associated type in Swift 3

這是我的示例代碼:

protocol P {

}

protocol B {

  associatedtype ID: P

}

class MyClass: B {
  enum ID: P {
    case one
    case two
  }
}

func process<T: B>(_ value: T.ID) {
  // do something
}

process(MyClass.ID.one) // Compile Error: cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'

如您所見,我使用參數定義泛型函數,該參數的類型是泛型類型 T關聯類型 我怎么稱呼這個功能? 我想使用MyClass.ID.one作為參數,但編譯器提供以下警告:

cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'

看來Swift通過從MyClass.ID開始為T.ID並且支持MyClassT從調用中推斷出T是一個問題。

如果您更改函數以獲取類型T的附加參數,則代碼將編譯並運行正常:

func process<T: B>(_ value: T.ID, _ workaround : T) {
  // do something
}

let workaround = MyClass()
process(MyClass.ID.one, workaround)

Swift設計人員可以通過兩種方式解決這個推理問題:

  • 修復推理引擎以允許此用例,或
  • 通過對函數簽名實施更嚴格的規則,使推理引擎更容易找出T

看來他們決定使用Swift 4的第二種方法,因為原始函數無法編譯,發出以下錯誤:

通用參數'T'未在函數簽名中使用

更好的解決方法是使用Java風格的方法傳遞類型而不是實例:

func process<T: B>(_ value: T.ID, _ workaround: T.Type) {
  // do something
}
...
process(MyClass.ID.one, MyClass.self)

注意:編輯基於tesch非常有見地的評論

dasblinkenlight為您當前實現無效的原因提供了一個很好的答案。 如果決定的解決方案是簡單地找到另一種方法來實現這個功能,那么我會選擇一個不那么hacky的解決方案:

extension B {
    static func process(_ value: Self.ID) {
        //do stuff
    }
}

MyClass.process(.one)

這利用了通過協議擴展Self實現的更靈活的類型推斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM