제네릭 형식을 반환하는 정적 메서드가있는 프로토콜을 만들려고합니다. 대부분의 경우 내가 가진 것이 합리적으로 잘 작동하는 것 같습니다. 확장 기능을 사용하여이 일반 값을 반환하려는 경우 문제가 발생합니다. 여기에 내가 가진 것이있다. 이 코드는 놀이터에 놓을 수 있습니다. 여기 일반 형식의 빠른 프로토콜
protocol AWDeserializer {
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> T?
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> [T]?
}
은 예입니다
는 여기에 내가 나 역 직렬화의 작업을 할 인스턴스를 만들 수 있습니다 다른 프로토콜을 만들어 그 다음 associatedtype
protocol AWSerializable {
associatedtype T
static func deserialize(dictionary: [String : Any]) -> T?
func serialize() -> [String : Any]
}
이 들어 내가 할 첫 번째 프로토콜입니다 이는 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
}
}
지금까지 너무 좋아. 문제는 AWDeserializer
프로토콜을 구현하기 위해 UserDefaults
에 extension
을 생성하려고 할 때 발생합니다.
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
}
}
여기에 문제가있는 것은 입니다.
이 쉽게 제안 된 솔루션을 적용하여 고정, 또는 바람직 return T.deserialize(dictionary: serialized) as? T
에 라인을 변경하지만이 선택 캐스트는 사실을 좋아하지 않는다 : 나는 다음과 같은 오류가 발생합니다 시작해야합니다. 이 캐스트를 필요로하지 않는 프로토콜을 정의 할 수있는 방법이 있습니까?
protocol AWDeserializer {
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> T? where T.T == T
func deserializeWithKey<T: AWSerializable>(_ key: String!) -> [T]? where T.T == T
}
대신 :
이 가능성이 있고 나는 원래 이것을 가지고 있었다. 나는 2 가지 문제에 부딪쳤다. 첫 번째는 클래스의 Extension에서이 프로토콜을 구현할 수 없다는 것입니다. 'init' 요구 사항은 내가 아는 한 이것을 불가능하게 만든다. 다른 문제는 클래스를 확장 할 때'init' 메쏘드가 수퍼 클래스에서 필요한 이니셜 라이저를 가지고 몇 가지 부작용을 가질 수 있다는 것입니다. – jervine10
만약 그렇다면'? 'AWSerializable.T'와'AWSerializable'은 다를 수 있습니다. Type, 그냥 AWSerializable.T'을 AWSerializable'으로 변환하면됩니다. – beeth0ven
이 프로토콜을 선언하는 유일한 방법입니까? 캐스트가 필요하지 않도록 AWDeserializer를 선언하는 더 좋은 방법이 있습니까? – jervine10