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 😊
まとめ
厳しい