まず最初に
最初に懺悔します。
someとanyを雰囲気で使ってました
本記事は、筆者がもう少し理解を深めるためのアウトプットです。
(一言で)Swiftにsomeとanyキーワードが導入された背景
安全に型を扱いながらパフォーマンスを向上させるため。
本記事では使い所やメリットなどに絞って書いていきます。
細かい挙動や仕様などは参考のリンク先を見ていただければと思います。
some
使い所
someキーワードは、戻り値などの複雑な型を外部に公開したくない時に使う。
メリット、デメリット
- メリット
- コンパイラ時に型が一意になる
- 型安全: 戻り値の具体的な型が外部から見えないため、関数の詳細を隠蔽できる
- パフォーマンス: コンパイラが具体的な型情報を持っているため、最適化が可能
- コンパイラ時に型が一意になる
- デメリット
- 汎用性の制限: someを使うと、返される型が常に同じである必要があり、異なる型を返すことができない → こういうことをした場合はanyを使用する
コードで見てみる
外部からの型の隠蔽
SwiftUIでのお決まり、計算型プロパティのbodyの型表記 some View
何かしらのViewに準拠したオブジェクトを返却するプロパティ。
下記コードはコンパイル時に、Textオブジェクトが返されることがわかる。
struct SampleView: View {
var body: some View {
Text("hoge")
}
}
ゆえに、こうも書ける。
けど、Viewの定義時には具体的な型は内部の実装に依存したいため、上記のように書いている。
struct SampleView: View {
var body: Text {
Text("hoge")
}
}
ジェネリクスの書き換え
ジェネリクスの関数をsomeの記載に書き換える。
protocol Animal {}
struct Dog: Animal {}
struct Cat: Animal {}
func walk<T: Animal>(with animal: T) {
print(type(of: animal), "と散歩中")
}
こう書き換えられる。
func walk(with animal: some Animal) {
print(type(of: animal), "と散歩中")
}
多少シンプルにすることができる。
ちなみにsomeの部分をanyに書き換えられるが、メモリのオーバーヘッドやパフォーマンスの問題もあるため、someで書くのが理想的。
any
使い所
特定のプロトコルに準拠する任意の型を受け入れる場合に使用する。
メリット、デメリット
- メリット
- コードの簡潔化: 多様な型を受け入れるため、コードが簡潔になる
- デメリット
- ランタイムのオーバーヘッド: any(存在型)は実行時に型情報を保持する必要があるため、パフォーマンスのオーバーヘッドが発生することがある
コードで見てみる
戻り値の型が実行時に決まる
func randomAnimal() -> any Animal {
Bool.random() ? Dog() : Cat()
}
こういったコードの場合はsomeを使用することができない。
参考
https://zenn.dev/fsh/articles/0fffd249fd54ca
https://jimaru.blog/programming/swift/swift-some-any/
認識誤りとかあれば、コメントでお願いします!