ジェネリクスとは?
今日はジェネリクスについてまとめたいと思います。
ジェネリクス(Generics)は、Swiftで型に依存しない柔軟で再利用可能なコードを書くための強力な仕組みです。これを活用すると、IntやStringといった具体的な型を意識することなくどんな型でも扱うことができるため、コードの汎用性が大きく向上します。
ジェネリクスはSwiftの特徴的な機能の一つであり、多くの場面で利用されます。
参考文献
実際にジェネリクスを書いてみる
実際にコードを記述してみます。
ジェネリクスでない関数
まずは通常のジェネリクスなしの関数です。下記のようにIntやStringを指定しなければなりません。
// 型を指定する必要がある場合
func returnString(_ value: String) -> String {
return value
}
func returnInt(_ value: Int) -> Int {
return value
}
var resultString = returnString("山田") // "山田"
var resultInt = returnInt(3) // 3
ジェネリクスの関数
// ジェネリクスを使用することで、どんな型でも対応できる
func returnValue<T>(_ value: T) -> T {
return value
}
var resultString = returnValue("山田") // "山田"
var resultInt = returnValue(3) // 3
さらにもう少しだけ工夫をしたバージョンです。こちらを使用し条件分岐を行なったりすることで更に汎用性の高いメソッドを作成することができ非常に便利です。
func startGenerics<T>(first: T, second: T) -> (T, T) {
return (first, second)
}
let intResult = startGenerics(first: 10, second: 20)
let stringResult = startGenerics(first: "Arsenal", second: "LOVE")
let doubleResult = startGenerics(first: 3.14, second: 2.71)
let boolResult = startGenerics(first: true, second: false)
// 様々な型を渡すことができるジェネリック関数
struct User {
let name: String
let age: Int
}
let user1 = User(name: "山田", age: 30)
let user2 = User(name: "佐藤", age: 25)
// 構造体もジェネリクスで扱える
let userResult = startGenerics(first: user1, second: user2)
print(intResult) // (10, 20)
print(stringResult) // ("Arsenal", "LOVE")
print(doubleResult) // (3.14, 2.71)
print(boolResult) // (true, false)
print(userResult) // (User(name: "山田", age: 30), User(name: "佐藤", age: 25))
Equatableプロトコル
Equatableプロトコルとは?
Equatableは、インスタンス同士が等しいか(==)を比較できる型に適用されるプロトコルです。
例えば、String、Int、Floatなどの型は、もともとEquatableに準拠しています。
ジェネリクス × Equatable
ジェネリクス関数にEquatableの制約を加えると、特定の型(等価比較できる型)だけに限定できます。
参考文献
// 型に制限を加えて、特定の型でのみ動作させることもできる
func startGenerics<T: Equatable>(first: T, second: T) -> (T, T) {
return (first, second)
}
このように、
- 同じ型でなければならない(T型)
- 比較できる型に限る(T: Equatable)
という2つの制約があるため、== を使った比較も安全にできるようになります(※今回は「==」を使っていませんが、できる状態になっています)。
これにより、さらに堅牢で安全なコードを書くことができます。
まとめ
使ってみるとわかりますが、ジェネリクスを使うことで型に縛られず様々なデータ型を扱うことができ、コードの再利用性と柔軟性が格段に向上しとても便利だと思いました。