簡體   English   中英

Swift:解碼任意協議類型

[英]Swift: Decode arbitrary protocol types

我正在嘗試解碼具有符合協議的可變屬性的JSON。

考慮以下結構集:

protocol P: Decodable {
    var id: String { get }
}

struct A: P {
    let id: String
    var someThing: Double
}

struct B: P {
    let id: String
    var anotherThing: String
}

struct S: Decodable {
    let id: String
    let instanceOfProtocol: P
}

我們正在嘗試解碼S

Decodable的自動綜合無法正常工作(因為解碼器無法知道P將被解碼為哪種類型),所以我嘗試在自定義初始化程序中執行以下操作:

選項1:詳盡檢查符合類型:

if let instance = try? container.decode(A.self, forKey: .instanceOfProtocol) {
    instanceOfProtocol = instance
} else if let instance = try? container.decode(B.self, forKey: .instanceOfProtocol) {
    instanceOfProtocol = instance
} else {
    throw NoConformingTypeError()
}

這可行,但是非常冗長,重復,並且伸縮性不佳,因此我正在尋找其他選擇。

選項2:(Ab)使用superDecoder

let possibleTypes: [P.Type] = [A.self, B.self]
let childDecoder = try container.superDecoder(forKey: .instanceOfProtocol)
let decoded: [P] = possibleTypes.compactMap { try? $0.init(from: childDecoder) }
guard let instance = decoded.first else { throw NoConformingTypeError() }
instanceOfProtocol = instance

這也可以正常工作,但是我不確定superDecoder是否打算以這種方式使用,或者將來是否會崩潰。

選項3:

let possibleTypes: [P.Type] = [A.self, B.self]
let decoded: [P] = possibleTypes.compactMap { try? container.decode($0, forKey: .instanceOfProtocol) }
guard let instance = decoded.first else { throw NoConformingTypeError() }
instanceOfProtocol = instance

到目前為止,這似乎是最好的選擇,但由於Ambiguous reference to member 'decode(_:forKey:)'Ambiguous reference to member 'decode(_:forKey:)' ,因此無法編譯。

編輯:

選項4:使用通用類型:

struct S<T: P>: Decodable {
    let id: String
    let instanceOfProtocol: T
}

這真是太好了,因為“ Decodable合成再次起作用了!

但是,現在我們必須知道類型T ,因為解碼站點現在需要一種類型:

try JSONDecoder().decode(S<A>.self, from: data)
try JSONDecoder().decode(S<B>.self, from: data)

在我們的用例中,我們不知道類型是什么,因此我們必須再次檢查這里...

使用通用類型:

struct S<T: P>: Decodable {
    let id: String
    let instanceOfProtocol: T
}

記住Protocol不是Type Swift是強類型語言。 因此,即使對象的調用者無法暴露實際的類型,它也必須首先知道所有對象的類型。

暫無
暫無

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

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