簡體   English   中英

Swift 泛型/不透明類型:嘗試使用協議一致性在泛型函數中的類型之間進行轉換

[英]Swift Generics/Opaque Types: trying to use protocol conformance to convert between types in a generic function

我正在構建一個Converter來將我的DataObject轉換為ModelObject ,反之亦然。 我目前有兩個功能來進行轉換。 每次轉換一個。

目前,我的兩個轉換函數都做同樣的事情,除了它所采用的類型和它返回的類型。 我希望我可以編寫一個能夠處理兩種轉換的通用函數,因為否則代碼完全相同。

這是我所得到的:顯然這些是簡化的示例

我已經構建了一個包含屬性要求和init()Protocol 我已經在DataObjectModelObject中實現了這個Protocol及其init()

我的Protocol

protocol MyProtocol {
    var id: UUID { get }
    var name: String? { get }

    init(id: UUID, name: String?)
}

我的DataObject

class DataObject: Object, MyProtocol {
    @Persisted(primaryKey: true) var id: UUID

    @Persisted var name: String?

    required convenience init(id: UUID, name: String?) {
        self.init()
        self.id = id
        self.name = name
    }
}

我的ModelObject

struct ModelObject: MyProtocol {
    var id: UUID
    var name: String?

    init(id: UUID, name: String?) {
        self.id = id
        self.name = name
    }
}

當前:這是當前正在進行轉換的示例。 每次轉換我都有一個這樣的。

static func buildModelObject(object: DataObject) -> ModelObject {
    let returnObject = ModelObject(id: object.id, name: object.name)
    return returnObject
}

所需的Converter功能:我希望完成這樣的事情。

static func buildObject<O: MyProtocol, R: MyProtocol>(objectIn: O, returnType: R.Type) -> R {
    let returnObject = returnType.init(id: objectIn.id, name: objectIn.name)
    return returnObject
}

我這樣稱呼它:

let object = Converter.buildObject(objectIn: dataObject, returnType: ModelObject.self)

顯然,這是行不通的。 錯誤: “協議 'MyProtocol' 作為一種類型不能符合協議本身”。 錯誤在函數調用上。 這是 XCode 在編譯時向我顯示的唯一錯誤。

我不確定在這里做什么或如何讓它工作。 我什至不相信此錯誤消息是否有任何幫助。

問題:

甚至有可能完成這樣的事情嗎? 如果是這樣,我錯過了什么? 我對 Swift 泛型仍然很陌生。

我沒有使用多個轉換函數的問題,因為它仍然比讓整個代碼庫陷入 Realm 特定的東西要好。 但是,鑒於這些函數本質上是相同的,我希望泛型能夠幫助將其他類似的代碼減少到一個函數中。

注意: DataObject是一個 Realm Object 我了解它們具有很酷的功能,例如實時/托管對象。 我們正在嘗試使用單個 API/入口點將 Persistence 層與應用程序的其余部分完全分開。 這就是我使用這些轉換器的原因。

你幾乎擁有它

func buildObject<R: MyProtocol>(objectIn: MyProtocol, returnType: R.Type) -> R {
    let returnObject = returnType.init(id: objectIn.id, name: objectIn.name)
    return returnObject
}

關鍵觀察:我們在任何時候都不需要objectIn的具體類型,所以只需要協議類型。

你不需要另一個論點。 返回類型已經提供了類型信息。

func buildObject<R: MyProtocol>(objectIn: some MyProtocol) -> R {
  .init(id: objectIn.id, name: objectIn.name)
}

正如評論中所建議的,這更習慣性地表示為初始化程序。

extension MyProtocol {
  init(_ objectIn: some MyProtocol) {
    self.init(id: objectIn.id, name: objectIn.name)
  }
}

暫無
暫無

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

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