#はじめに
今回はオブジェクト指向について説明します。
オブジェクト指向はSwiftだけの話ではなくプログラミングの手法、考え方の1つです。
概念といった方がいいかもしれません。
そのため抽象的な内容になってしまいます。
わからなくてもこんな感じの考え方なのかー程度に捉えておいてもいいかもしれません。
#オブジェクト指向
##オブジェクト指向とは
冒頭でいったようにオブジェクト指向はプログラミングの考え方の1つです。
Swiftはオブジェクト指向言語の1つではありますが、Swiftを使っているだけではオブジェクト指向でプログラミングをしているとは言えないと考えています。
オブジェクト指向の考え方に則った上でコーディングすることで初めてオブジェクト指向プログラミングをしていると言えます。
ではオブジェクト指向とはどのような考え方なのでしょうか?
一言でいうと「データのまとまりを1つのモノ(オブジェクト)として捉えてプログラミングする」考え方です。
ここでいうモノとは実体のある人間、テレビなどだけではなく実体のない天気、予定といった概念も意味します。
つまりプログラミングの対象となる全てがオブジェクトとして表されます。
オブジェクトには振る舞い(メソッド)があります。
オブジェクト指向では、あるオブジェクトが別のオブジェクトをメソッドを通して操作する、さらにその別のオブジェクトを...というイメージでプログラムを記述していきます。
具体的な例をあげます。
これは人が車を動かす時の例です。
それぞれが全てオブジェクトで矢印がメソッドを意味しています。
人間が車を動かすとき、車オブジェクトのアクセルメソッドを使って操作しています。
また車オブジェクトはエンジンオブジェクトを、エンジンオブジェクトはタイヤオブジェクトを操作します。
その結果車が動くという結果となります。
ここで注目したいのは人間オブジェクトはアクセルメソッドを呼んだ結果、車オブジェクトがどうやって車を動かしているのか知る必要がないということです。
内部でどういう処理をしてようと人間オブジェクトにとっては関係なく、移動したという結果がわかればいいということです。
これは現実世界の車の運転でも同じでアクセルを踏めば勝手に車が進んでくれます。
このように各オブジェクト間で役割分担しプログラミングしていくという考え方がオブジェクト指向の基本となります。
##クラス
オブジェクトはクラスから作られます。
クラスはオブジェクトの設計図や雛形のようなイメージです。
定義の仕方などはこちらで紹介しています。
山田太郎という人がいたとします。
この山田太郎はオブジェクトです。
山田太郎は人間です。
人間には名前があります。他にも手、足、鼻など人間を構成する要素は色々あります。
この人間という種類を定義するものがクラスです。
つまり山田太郎は人間クラスから作成されたオブジェクトという関係を持ちます。
オブジェクトを抽象化したものがクラスです。
##オブジェクト指向の原則
オブジェクト指向ではクラスを定義→オブジェクトを作成→メソッドを実行するという順序で実装しますが、このクラス定義が最も重要です。
クラスを定義するとき継承、カプセル化、ポリモーフィズムという考え方が必要になります。
###継承
継承とはあるクラスの機能を引き継いで新しいクラスを作るという考え方です。
例えば犬クラス、猫クラスがあったとします。
この2つのクラスは「食べる」という振る舞いを持ちます。
食べる処理はそれぞれ同じ処理ですがどのように実装しますか?
継承がなければ犬クラス、猫クラスそれぞれに「食べる」というメソッドを定義しなければなりません。
2クラスであればそれほど手間ではありませんが、これが10クラスとなると相当に手間です。
さらにプログラムにバグがあったとなると全てのクラスで同じ修正をしなければなりません。
そこで継承という考え方を使います。
犬、猫をさらに抽象化すると生物と考えられます。
生物は「食べる」という機能を持つので生物クラスに「食べる」メソッドを定義します。
犬クラス、猫クラスを生物クラスを継承して作成すると犬クラス、猫クラスは生物クラスの「食べる」メソッドを引き継ぎ、それぞれのクラスのメソッドとして使用できます。
このように機能を引き継いでいく考え方を継承といいます。
上記例ではメソッドを継承していますがプロパティも継承されます。
このとき生物クラスを親クラス(スーパークラス)、犬クラス、猫クラスを生物クラスの**子クラス(サブクラス)**と呼びます。
またオーバーライドといって親クラスのメソッドを子クラスで上書きしメソッドの処理を追加することも継承の重要な機能です。
上記の例の場合、犬クラスのeat()
を呼び出すと「もぐもぐ」の後に「わん」と表示されます。
###カプセル化
カプセルには「覆い隠す」というような意味があります。
プログラムにおけるカプセル化とは必要なもの以外、外から見えなくすることを意味します。
「隠蔽する」と表現したりします。
なぜ隠蔽する必要があるのかというと、外から余計なデータを変更させないようにしてオブジェクト内部の処理が壊れないようにするためです。
オブジェクトのメソッドは内部でプロパティの値を参照したり変更したりします。
この値を何も知らない人から勝手に変更されると想定していない動作を引き起こすことがあります。
車クラスを例にあげます。
車クラスには「アクセル」メソッドがあります。
これは外のオブジェクトが操作してもいいメソッドです。
「アクセル」メソッドの中では
1.ガソリンをエンジンに供給する
2.エンジンを点火する
3.タービンを回す
4.タイヤを回す
というようなそれぞれのメソッドを呼び出して処理しています。
これらの内部で呼び出されているメソッドには呼び出す順番が決まっていて、それらは車クラスの中で慎重に制御されています。
ここで何も知らない人が外からいきなり「2.エンジンを点火する」を呼び出してしまったらエンジンが壊れてしまうかもしれません。
そこで1〜4のメソッドを隠蔽することで外から呼び出せないようにすることで車が壊れないようにします。
このように必要なもの以外は外から見えなくしてしまうことをカプセル化といいます。
また隠蔽したメソッドをprivateメソッド、外からもアクセスできるメソッドをpublicメソッドと言います。
同様にプロパティにもprivate、publicを設定することができます。
###ポリモーフィズム
ポリモーフィズムは多様性などと訳されます。
これは少し難しい概念かもしれません。
また車を例にあげて説明します。
現実世界で車を運転する場合AT車であればアクセルを踏めば車は動きます。
SUV、セダン、ミニバンなど車の種類は色々ありますが、運転するそれが何であってもアクセルを踏めば進むということは知っています。
それは車はアクセルを踏めば進むものと決まっているからです。
ですがアクセル踏んでから車が動くまでの内部の処理はそれぞれの車によって違います。
内部の動きが異なっても同じ操作で実行できるようにすること、同じメソッド名で振る舞い変えることをポリモーフィズムといいます。
プログラムではこれを**インターフェース(interface)という機能を使って実現します。
Swiftではプロトコル(protocol)**という機能になります。
プロトコルは約束事、取り決めという意味です。
車プロトコルはアクセルというメソッドを呼び出すと進むということを決めておきます。
すると呼び出し側はSUVクラス、セダンクラス、ミニバンクラスということを意識することなくアクセルメソッドを呼び出せるようになります。
プロトコルはこのような抽象的な定義をするときに使用します。
#最後に
今回はオブジェクト指向という考え方について説明しました。
おそらくまだピンと来ていない人が多いかと思います。
これは具体的に自分でクラスを作り実装していかないと理解するのは難しいところかと思います。
というよりオブジェクト指向自体がプログラミング設計に対する考え方、概念で抽象的なものです。
実際クラスに対する考え方は意見が分かれるところでもあり明確なものはありません。
とりあえず今はなんとなくこんな感じなのかなー程度で理解してもらえれば問題ありません。
それぞれの具体的な実装方法については別途投稿していきます。
今回の内容は以上です。
本記事とは別でプログラミング未経験からiOSアプリ開発が行えるようになることを目的とした記事を連載しています。
連載は以下にまとめていますのでそちらも是非もご覧ください。
http://naoyalog.com/