[Swift3]何となく分かった気になれる「ジェネリクス」

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る
Swift

基本的な文法と知識さえあればアプリの開発はできるけれども、初心者にはやっぱり訳がわからないアレやコレが登場するのがSwift3。

そんなアレコレを、せめて「何となく分かった」というくらいにはしたい人(筆者含む)のためのシリーズ。今回は「ジェネリクス」のお話。

ジェネリクスの何がすごいのか

こういうのはやっぱりメリットがわからないと理解が進まないと思う。ジェネリクスってやつは使うとどんな良いことがあるのか。

例えば、キーと値を引数に指定してデータを登録するような関数「touroku」を作ろうとした場合。touroku(“田中”,12345)というふうに使うと「田中」というキーで「12345」というデータが保存される具合。
ざっくり書くとこんな感じになるのではないだろうか。

 

しかしこれだと大問題。valueがInt型でないと(当然だけど)エラーになってしまう。

 

じゃあ汎用性を持たせてやるぜ!というノリで、valueがString型・Double型のバージョンを作ればとりあえずは解決する。
しかし似たような関数をたくさん作るとコードが肥大化するし、そもそも他の型が登場したらどうするんだという話になってしまう(BoolとかURLとか)。

 

ここで登場するのがジェネリクス。試しに関数を「1つだけ」、以下のように作ってみる。するとあら不思議、valueがどんな型でもエラーにならないのだ。

 

ということで、超ざっくりジェネリクスのすごい点をまとめると

「同じ処理をいろいろな型についてやりたい時、コードが簡潔になるよ!あと汎用性が上がるよ!」

といった感じである。

ジェネリクスの基本的な使い方

基本の基本

基本は

  1. 「どんな型でも良いよ」を表す文字を、<>の中に書く
  2. 普段型の名前を書くのと同じように、1で決めた名前を型名に指定する

の2段階。

ジェネリクスの基本を説明する画像

ちなみに「T」としている文字は、開発者が自由に決めて良い。「U」でも「V」でも良いし、複数文字の単語を使っても良い。

2つ以上の別々な型を使う

例えば、以下のような関数があるとする。

 

引数に指定するxとyは型の指定がないので、IntだろうがStringだろうが何を入れても良い。

しかし、両者ともに「T」という同じ型名を使用しているため、xとyは同じ型である必要がある

 

今回のように「型は何でも良いし、2つの型が違っていても良い」という条件にしたい時は、以下の通り別々の文字を型名に指定する必要がある。

型について無法地帯にならないの?

実行時エラーにならないよう歯止めがかかっている

「どんな型でも良い」というと、思わぬ型が入って実行時エラーになったりして無法地帯になるのではないか?という疑問がよぎる。
しかしそのあたりはちゃんと制御してくれるのがSwiftさん。

例えば、ジェネリクスを使用して2つの値を比較する関数を以下のように作ってみる。しかし、このままだとコンパイルエラーとなって実行はできない。

 

エラーの内容はこう。

Binary operator ‘>’ cannot be applied to two ‘T’ operands

どんな型でも良いよーと指定した「T」型の値は、比較演算子を使って比較することができないよ、という内容だ。
確かに、例えばBool型やURL型など、全ての型が比較可能というわけではない。ということで、型の違いによって思わぬエラーを招かないようにSwift側で歯止めをかけているわけだ。

型にある程度の制限をかける

では、先述のような「ジェネリクスを使った、2つの引数を比較する処理」は実現不可能なのかというと、そうではない。

compare<T>の部分を、compare<T: Comparable>と修正する。すると先ほど出たエラーが消え、ちゃんと関数が使えるようになる。

 

鍵は、修正した<T: Comparable>の部分。このように書くと「Tはどんな型でも良いけど、比較可能な型じゃなきゃダメだよ」という意味になる。
このComparableの部分(従わなければならないルール)を「プロトコル」というらしい。

ジェネリクスの応用を説明した画像

この状態で実際に関数を使うと、IntやDouble・Stringの比較は問題なく行える。一方でComparableというルールに当てはまらないBool型やURL型では、コンパイルエラーとなる。

 

プロトコルには他にも「Equatable」や「Hashable」など色々存在する。

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る

SNSでもご購読できます。