2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ジェネリクスで Optional にキャストする

Last updated at Posted at 2017-07-20

表題通りですが、一筋縄ではいかなかったので備忘録として残します。

ジェネリクスを使わない場合、下記は正しくキャストできます。

let hoge: Any? = nil
hoge as! String?  // nil

しかし、ジェネリクス関数で同様のことを行う場合、 force unwrap によるエラーが発生してしまいます。

func convert<T>(_ value: Any?) -> T {
    return value as! T
}

convert(nil) as String?  // fatal error: unexpectedly found nil while unwrapping an Optional value

これは、もう一つジェネリクス関数を経由することで回避することができます。

func convert<T>(_ value: Any?) -> T {
    func cast<U, V>(_ value: U, to type: V.Type) -> V {
        return value as! V
    }
    return cast(value, to: T.self)
}

convert(nil) as String?  // nil

:thinking:


※ 達成したかったことは Optional、非 Optional どちらも許容できるキャストの定義です。

struct Hoge {
    let val1: String
    let val2: String?
}

Hoge(val1: convert(dict["val1"]),
     val2: convert(dict["val2"]))


// 逐一 `as` を書きたくない
Hoge(val1: dict["val1"] as! String,
     val2: dict["val2"] as? String)
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?