[英]Swift Generics/Opaque Types: trying to use protocol conformance to convert between types in a generic function
我正在構建一個Converter
來將我的DataObject
轉換為ModelObject
,反之亦然。 我目前有兩個功能來進行轉換。 每次轉換一個。
目前,我的兩個轉換函數都做同樣的事情,除了它所采用的類型和它返回的類型。 我希望我可以編寫一個能夠處理兩種轉換的通用函數,因為否則代碼完全相同。
這是我所得到的:顯然這些是簡化的示例
我已經構建了一個包含屬性要求和init()
的Protocol
。 我已經在DataObject
和ModelObject
中實現了這個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.