ジェネリックなサブスクリプトとエクステンション
サブスクリプトとエクステンションに制約を適用します。
「ジェネリックなサブスクリプトとエクステンション」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
ジェネリックな添字
添字にはジェネリック型パラメーターを独自に指定できます。これは、それを囲む型とは独立しています。そのため、1つの添字で多くの入力型に対応できます。
struct Lookup {
let data = [1, 2, 3, 4, 5]
subscript<S: Sequence>(indices idx: S) -> [Int] where S.Element == Int {
idx.map { data[$0] }
}
}
print(Lookup()[indices: [0, 2, 4]])なぜジェネリックな添字を使うのか
任意のIntのSequenceを受け取れるため、同じ添字にArray、Set、Rangeのインデックスを渡せます。
struct Lookup {
let data = [10, 20, 30, 40]
subscript<S: Sequence>(_ idx: S) -> [Int] where S.Element == Int {
idx.map { data[$0] }
}
}
let l = Lookup()
print(l[0...1])
print(l[[3, 0]])制約付き拡張
extension ... whereを使うと、制約を満たす場合にのみ存在するメンバーを追加できます。対応するジェネリック引数の場合に限り、その型にメンバーが現れます。
extension Array where Element: Numeric {
func sumAll() -> Element { reduce(0, +) }
}
print([1, 2, 3].sumAll())
print([1.5, 2.5].sumAll())特定の要素型に対する拡張
where Element == Stringを使うと、文字列の配列にのみ、String専用のヘルパーを追加できます。
extension Array where Element == String {
func shout() -> [String] { map { $0.uppercased() + "!" } }
}
print(["hi", "bye"].shout())プロトコルを使った制約付き拡張
要素がカスタムプロトコルに適合する場合に、機能を追加します。
protocol Priced { var price: Double { get } }
struct Item: Priced { let price: Double }
extension Collection where Element: Priced {
var total: Double { reduce(0) { $0 + $1.price } }
}
print([Item(price: 2), Item(price: 3)].total)Optionalを返すジェネリックな添字
添字はジェネリックにして、Optionalを返すこともできます。たとえば、コレクションを安全にインデックス付けできます。
extension Array {
subscript(safe i: Int) -> Element? {
indices.contains(i) ? self[i] : nil
}
}
print([1, 2, 3][safe: 1] ?? -1)
print([1, 2, 3][safe: 9] ?? -1)Dictionaryのジェネリックな添字
ジェネリックな添字では、キーのシーケンスを受け取り、対応する値を返せます。
extension Dictionary {
subscript<S: Sequence>(keys ks: S) -> [Value] where S.Element == Key {
ks.compactMap { self[$0] }
}
}
let d = ["a": 1, "b": 2, "c": 3]
print(d[keys: ["a", "c"]].sorted())Selfに対するwhereとの組み合わせ
ジェネリック型の拡張では、ラップされた型に制約を指定し、用途に合わせたAPIを公開できます。
struct Stack<T> { var items: [T] = [] }
extension Stack where T: Comparable {
var peakMax: T? { items.max() }
}
var s = Stack<Int>(); s.items = [3, 9, 1]
print(s.peakMax!)複数のパラメーターを持つジェネリックな添字
添字には、複数の引数と独自の型パラメーターを同時に指定できます。
struct Grid {
let rows = [[1, 2], [3, 4]]
subscript(_ r: Int, _ c: Int) -> Int { rows[r][c] }
}
print(Grid()[1, 0])読み取り専用と読み書き可能
プロパティと同様に、添字にはgetだけを指定することも、変更可能にするためにgetとsetの両方を指定することもできます。
struct Pad {
var values = [0, 0, 0]
subscript(i: Int) -> Int {
get { values[i] }
set { values[i] = newValue }
}
}
var p = Pad(); p[1] = 7
print(p.values)総合演習
ジェネリックな添字と制約付き拡張を組み合わせると、使用される要素型や引数型に適応する、表現力と型安全性を備えたAPIを構築できます。
extension Array where Element: Comparable {
subscript(topAfterSort i: Int) -> Element { sorted()[i] }
}
print([5, 1, 9, 3][topAfterSort: 0])理解度チェック
ジェネリックな添字と制約付き拡張についての理解度を確認しましょう。
まとめ
ジェネリックな添字では、独自の型パラメーターとwhere句を宣言でき、1つの添字で多くの入力型を受け取れます。制約付き拡張(where Element: ...または== ...)では、条件を満たす場合に限ってメンバーを追加できます。これらを組み合わせることで、型安全で柔軟なAPIを構築できます。
よくある質問
「ジェネリックなサブスクリプトとエクステンション」レッスンは無料ですか?
はい。「ジェネリックなサブスクリプトとエクステンション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「ジェネリックなサブスクリプトとエクステンション」で何を学びますか?
サブスクリプトとエクステンションに制約を適用します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「ジェネリックなサブスクリプトとエクステンション」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。