2
我想創建一個協議,它有一個返回泛型類型的靜態方法。在大多數情況下,我似乎工作得很好。當我想使用擴展來返回這個通用值時,挑戰就出現了。這是我的。此代碼可以放置在操場上。與泛型類型的Swift協議
這裏的第一個協議,我想它包含associatedtype
protocol AWSerializable {
associatedtype T
static func deserialize(dictionary: [String : Any]) -> T?
func serialize() -> [String : Any]
}
然後,我創建了另一個協議,它允許我創建做反序列化的操作實例:
protocol AWDeserializer {
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> T?
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> [T]?
}
下面是一個例子愉快地實施AWSerializable
協議:
class FooBar: AWSerializable {
typealias T = FooBar
var foo = ""
var bar = ""
static func deserialize(dictionary: [String : Any]) -> FooBar? {
let fooBar = FooBar()
fooBar.foo = (dictionary["foo"] as? String) ?? ""
fooBar.bar = (dictionary["bar"] as? String) ?? ""
return fooBar
}
func serialize() -> [String : Any] {
var serialized = [String : Any]()
serialized["foo"] = foo
serialized["bar"] = bar
return serialized
}
}
到目前爲止好。當我想在UserDefaults
上創建extension
來實現AWDeserializer
協議時,挑戰就出現了。
extension UserDefaults: AWDeserializer {
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> T? {
if let serialized = UserDefaults.standard.object(forKey: key) as? [String : Any] {
return T.deserialize(dictionary: serialized)
}
return nil
}
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> [T]? {
if let data = UserDefaults.standard.array(forKey: key) as? [[String : Any]] {
var values = [T]()
for entry in data {
if let value = T.deserialize(dictionary: entry) {
values.append(value)
}
}
return values
}
return nil
}
}
這裏的問題是與T.deserialize(dictionary: serialized)
。我得到以下錯誤:
這很容易通過應用建議的解決方法固定,最好通過改變線路return T.deserialize(dictionary: serialized) as? T
但我不喜歡的事實,這可選演員陣容需要開始。有沒有辦法定義不需要這種轉換的協議?
這是一個可能性,我原本是有這個的。我遇到了兩個問題。首先是我無法在擴展類上實現此協議。就我所知,'init'要求使得這個不可能。另一個問題是擴展一個類時,'init'方法可能會在超類中具有所需的初始化器的一些副作用。 – jervine10
如果是這樣的話? T'是必需的,因爲'AWSerializable.T'和'AWSerializable'可能是不同的類型,所以使用''AWSerializable.T'就可以'AWSerializable'。 – beeth0ven
這是宣佈這些協議的唯一方法嗎?是否有更好的方法來聲明'AWDeserializer',以便不需要強制轉換? – jervine10