3
decode(_forKey:)
はその最初のパラメータを無視し、代わりにジェネリックパラメータに依存してデコードするタイプを決定します。この場合、最初のパラメータは何ですか?なぜ `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?
第1パラメータは、呼び出しに対する汎用パラメータの特殊化に使用されます。スーパークラスのメタタイプの変数にサブクラスメタタイプのインスタンスを渡して渡すのはちょっと奇妙です。ここで行う必要のある具体的なことがありますが、 'Lion.self'を直接渡すことはできません。 –
しかし、ジェネリックパラメータは、呼び出し元が戻り値で行うことから推測できますか? (もちろん、この例では 'Lion.self'を渡すことができますが、実行時に決定されたさまざまなサブクラスをデコードすることができます。) – andyvn22
いいえ、常にそうとは限りません - 戻り値の型追跡が困難なあいまいさにつながる可能性があります。そのあいまいさを防ぐための唯一の保証された方法は、メタタイプの引数を渡すことです。コードで汎用引数の代わりに渡される具象メタタイプを使用することは可能ですが、これはかなりユニークな使用例です。ただし、実行時に型を切り替え、正しい静的型でコールをデコードすることは可能です。 –