some / any / opaque type
| 対応: | Swift 5.7(2022) |
|---|
Swift 5.7 以降、プロトコル型の扱い方として『some』(不透明型)と『any』(存在型)の2つのキーワードが導入されました。どちらもプロトコルを型として使う仕組みです。
構文
// some: 不透明型(戻り値が特定の1つの具体型に固定される)
func makeShape() -> some Shape {
return Circle(radius: 5)
}
// any: 存在型(任意のプロトコル準拠型を格納できる)
var shapes: [any Shape] = [Circle(radius: 5), Rectangle(width: 3, height: 4)]
// プライマリ関連型(Swift 5.7+)
func process(_ values: some Collection<Int>) { }
構文一覧
| 構文 | 概要 |
|---|---|
| some プロトコル | 不透明型。コンパイラが具体型を知っているが呼び出し側には隠す。戻り値型や引数型に使います。 |
| any プロトコル | 存在型。任意のプロトコル準拠型を格納できる。異なる型を配列に混在させる場合に使います。 |
| some Collection<T> | プライマリ関連型構文。Collection の要素が T であることを指定します。 |
サンプルコード
sample_some_any_opaque.swift
// プロトコルの定義
protocol Pilot {
var name: String { get }
func unitName() -> String
}
struct EvaUnit00: Pilot {
let name: String
func unitName() -> String { return "零号機" }
}
struct EvaUnit01: Pilot {
let name: String
func unitName() -> String { return "初号機" }
}
struct EvaUnit02: Pilot {
let name: String
func unitName() -> String { return "弐号機" }
}
// some: 戻り値が1つの固定した具体型(呼び出し側は知らない)
func makeMainPilot() -> some Pilot {
return EvaUnit01(name: "碇シンジ")
}
let mainPilot = makeMainPilot()
print("\(mainPilot.name): \(mainPilot.unitName())")
// any: 異なる具体型を同じ型として扱える存在型
let pilots: [any Pilot] = [
EvaUnit00(name: "綾波レイ"),
EvaUnit01(name: "碇シンジ"),
EvaUnit02(name: "惣流アスカ")
]
for pilot in pilots {
print("\(pilot.name): \(pilot.unitName())")
}
// some と any の違い
// some: 関数が常に同じ具体型を返す(コンパイラが最適化できる)
// any: 任意の型を格納できる(ボックス化によるオーバーヘッドあり)
// ボックス化(boxing)とは、値をヒープメモリに配置して間接的に参照する処理で、パフォーマンスのオーバーヘッドが生じます。
// Swift 5.7+ のプライマリ関連型構文
func sumAll(_ numbers: some Collection<Int>) -> Int {
return numbers.reduce(0, +)
}
print("合計: \(sumAll([1, 2, 3, 4, 5]))")
print("合計: \(sumAll(Set([10, 20, 30])))")
swift some_any_opaque.swift 碇シンジ: 初号機 綾波レイ: 零号機 碇シンジ: 初号機 惣流アスカ: 弐号機 合計: 15 合計: 60
概要
『some』は「呼び出し側には型を隠すが、コンパイラは具体型を知っている」不透明型です。関数が常に同じ具体型を返す場合に使い、パフォーマンスが良好です。SwiftUIの『body: some View』がこの典型例です。
『any』は「任意のプロトコル準拠型を格納できる」存在型です。異なる型を配列に混在させるなど、実行時に型が変わる場面で使います。Swift 5.7 以降では、プロトコルを型として使う際に any キーワードが必要になりました。some との混同に注意してください。
ジェネリック関数についてはジェネリック関数 / 型パラメータを参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。