为什么 `decode(_:forKey:)` 会忽略它的第一个参数?
Why does `decode(_:forKey:)` ignore its first parameter?
似乎 decode(_forKey:)
忽略了它的第一个参数,而是依靠通用参数来决定要解码的类型。如果是这样,第一个参数是干什么用的?
class Cat: Codable {
func speak() -> String { return "Meow" }
}
class Lion: Cat {
override func speak() -> String { return "Roar!" }
}
class Person: Codable {
let firstPet: Cat
let secondPet: Cat
init(firstPet: Cat, secondPet: Cat) {
self.firstPet = firstPet
self.secondPet = secondPet
}
enum CodingKeys: CodingKey { case firstPet, secondPet }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.firstPet = try container.decode(Lion.self, forKey: .firstPet)
let typeOfCat: Cat.Type = Lion.self
self.secondPet = try container.decode(typeOfCat, forKey: .secondPet)
}
}
let before = Person(firstPet: Lion(), secondPet: Lion())
let after = try! JSONDecoder().decode(Person.self, from: JSONEncoder().encode(before))
after.firstPet.speak() //"Roar!"
after.secondPet.speak() //"Meow" ...really?
decode(...)
调用的元类型参数用于专门化通用参数。 Swift 没有像 C++ 那样手动特化泛型的语法(例如 decode<Int>(forKey: ...)
),因此这是一种将泛型参数绑定到具体类型的方法。
传入元类型(而不是依赖 return 类型来提供解析)的好处是表达式的结果是明确的。依赖 return 结果可能会导致一些令人惊讶的情况:
protocol DefaultInitializable {
init()
}
func defaultValue<T : DefaultInitializable>() -> T {
return T()
}
func foo(_ value: Int) {
print(value)
}
foo(defaultValue())
结果
Untitled.swift:13:5: error: generic parameter 'T' could not be inferred
foo(defaultValue())
^
Untitled.swift:5:6: note: in call to function 'defaultValue'
func defaultValue<T : DefaultInitializable>() -> T {
^
有了明确的元类型,这就不是问题了。
至于为什么要在您传入的元类型的具体实例上使用泛型类型——具体元类型实例具有与其自身不同的静态类型通常是意想不到的。
似乎 decode(_forKey:)
忽略了它的第一个参数,而是依靠通用参数来决定要解码的类型。如果是这样,第一个参数是干什么用的?
class Cat: Codable {
func speak() -> String { return "Meow" }
}
class Lion: Cat {
override func speak() -> String { return "Roar!" }
}
class Person: Codable {
let firstPet: Cat
let secondPet: Cat
init(firstPet: Cat, secondPet: Cat) {
self.firstPet = firstPet
self.secondPet = secondPet
}
enum CodingKeys: CodingKey { case firstPet, secondPet }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.firstPet = try container.decode(Lion.self, forKey: .firstPet)
let typeOfCat: Cat.Type = Lion.self
self.secondPet = try container.decode(typeOfCat, forKey: .secondPet)
}
}
let before = Person(firstPet: Lion(), secondPet: Lion())
let after = try! JSONDecoder().decode(Person.self, from: JSONEncoder().encode(before))
after.firstPet.speak() //"Roar!"
after.secondPet.speak() //"Meow" ...really?
decode(...)
调用的元类型参数用于专门化通用参数。 Swift 没有像 C++ 那样手动特化泛型的语法(例如 decode<Int>(forKey: ...)
),因此这是一种将泛型参数绑定到具体类型的方法。
传入元类型(而不是依赖 return 类型来提供解析)的好处是表达式的结果是明确的。依赖 return 结果可能会导致一些令人惊讶的情况:
protocol DefaultInitializable {
init()
}
func defaultValue<T : DefaultInitializable>() -> T {
return T()
}
func foo(_ value: Int) {
print(value)
}
foo(defaultValue())
结果
Untitled.swift:13:5: error: generic parameter 'T' could not be inferred
foo(defaultValue())
^
Untitled.swift:5:6: note: in call to function 'defaultValue'
func defaultValue<T : DefaultInitializable>() -> T {
^
有了明确的元类型,这就不是问题了。
至于为什么要在您传入的元类型的具体实例上使用泛型类型——具体元类型实例具有与其自身不同的静态类型通常是意想不到的。