CustomStringConvertible でミスっても型検査で気付けない問題の対処方法です。
本題
Swift は、ある型が文字列での表現形式を持っていることを表明する
CustomStringConvertible という protocol があります。
この protocol は、description という文字列のプロパティを持っていれば実装できます。そして、String(describing:) は与えられた引数が CustomStringConvertible ならば、この description を使うという仕様になっています。 例えば、次のように書けます:
struct Foo: CustomStringConvertible {
let description: String
}
let foo = Foo(description: "😇")
let fooString = String(describing: foo) // OK
さて、ここで問題なのは String(describing:) がどんな型でも受け取れてしまうことです。そのため、CustomStringConvertible を実装し忘れても、型チェックでは気づけないのです:
extension String {
init(describingSafely x: CustomStringConvertible) {
self = x.description
}
}
struct Ok: CustomStringConvertible {
let description = "ok"
}
struct Ng {
}
print(String(describing: Ok())) // OK
print(String(describing: Ng())) // OK 😇アッ
そのため、下のような厳しめな対応をしておくと、CustomStringConvertible を忘れることがないでしょう:
extension String {
init(describingSafely x: CustomStringConvertible) {
self = x.description
}
}
struct Ok: CustomStringConvertible {
let description = "ok"
}
struct Ng {
}
print(String(describingSafely: Ok())) // OK
print(String(describingSafely: Ng())) // NG 😊
まとめ
厳しい