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