フルスタックエンジニアのノウハウ
2020.11.25    2021.01.05

今日こそオブジェクト指向を理解する

今日こそオブジェクト指向を理解する

この記事の動画版はこちら

チャンネル登録お願いします!



今回は「オブジェクト指向」について、初心者向けに分かりやすくご説明していきます。


オブジェクト指向は、プログラミングを学んでいく上で誰もが一度はぶつかる壁だと思います。


概念としては何となく理解出来ても、じゃあ実際どんな時に使うのかどんなメリットがあるのか、なかなか分かりづらいですよね。


ということで、今回は出来るだけ「具体例に沿って」説明していきたいと思います。



なぜオブジェクト指向が必要なのか?


まず最初に、そもそも「なぜオブジェクト指向なんてものが必要なのか?」という点を知っておきましょう。


細かい技術や概念の話よりも、その根底にあるものを知ることで理解がしやすくなると思います。


もちろん生まれた経緯や、使われるシーンなどで考え方は色々あると思いますが、


僕が考えるオブジェクト指向が必要な理由、


それは「面倒くさいから」です。


プログラマーは基本「面倒くさがり」です。
一度書いた処理は、出来ればもう二度と書きたくない。


でも、プログラムを作っていると、色々な場所で同じ処理が必要になることが多々あります。


同じ処理を何度も書くのは面倒くさい、だったらその処理を「テンプレ化」して再利用出来るようにしちゃおう!


これがオブジェクト指向の根底にあります。


オブジェクト指向という方法でプログラムを作ることで、一度書いたプログラムを再利用しやすくなったりより少ないコードで処理が実現出来るようになるメリットがあります。


ただ、逆にオブジェクト指向を全く使わなくてもWebアプリを作ることは出来ます。


使わなくても良いけど、使えばより便利ということですね。



関数との違い


以前の記事で「関数」の話をしました。


関連記事

関数とは何か?


再利用出来そうな処理は「関数」として定義しておけば、後から色々な場所で使いたい時に、その関数を呼び出すだけで処理を行ってくれる便利なものでしたね。


しかし、関数はあくまで決められた1つの処理を行ってくれるものでしかありません。


実際のプログラムでは、1つの処理だけでなく、色々なデータを準備して、いくつもの処理手順を行うことがあり、それら一連の処理が色々な場所で使われるような場合もあります。


例えば「メール送信処理」


単純なメール送信なら、関数を1つ呼び出すだけで良いんですが、例えば、HTMLメールの送信ファイルの添付といったさらに高機能なことを行おうとすると、


・データの準備
・内容のチェック
・ヘッダー情報やボディ情報の設定
・送信処理
・送信後のチェック処理


など、様々な処理手順が必要になります。


そして、メール送信はアプリの様々な場所で行われるので、これら一連の処理を毎回毎回書くのは面倒です。


そこで、一連の処理に使う「変数」や「関数」群を、ひとまとめにしてテンプレ化しておこうと考えます。




処理に必要な変数関数を煩雑に管理するのではなく、ある役割を行う「物(=オブジェクト)」として定義しておこう。


この例の場合は、「メール送信を行う物」として定義しておこう。

そうすれば再利用もしやすいよね!という考え方。


これが「オブジェクト指向」です。



クラスとインスタンス


そして、この定義されたテンプレのことを「クラス」と言います。




クラスには、この処理に必要な「データ:変数」「処理:関数」が含まれます。


それぞれ「プロパティ」「メソッド」と呼ばれます。



なお、このクラスはあくまで「テンプレート」です。


実際にメールを送る際は、メールの件名や文面、宛先は毎回異なるので、このテンプレを元にして、実際のデータをセットしたものを作成します。これを「インスタンス」といいます。




設計図(クラス)を元に、具体的なもの(インスタンス)を作るというイメージです。


アプリの中の様々な場所でこのクラスの機能を使いたい場合は、それぞれでインスタンス化して使います。



オブジェクト指向のメリット


このように、オブジェクト指向では、単純な関数とは異なり、必要な「データ」「処理」ひとまとめにして管理出来るというメリットがあります。




オブジェクトとして、ひとまとめに管理されているため、このオブジェクト自体を変数として持ち運んだりといった扱い方も出来ます。



そして、オブジェクト指向では、さらに3つのメリットがあります。



メリット①「クラスを継承出来る」


継承とは「能力を引き継ぐこと」です。


あるクラスの能力を引き継いだ別のクラスを作ることが出来ます。


例えば、先ほどのMailクラスには基本的なメール送信の処理が含まれていますが、絵文字を送る機能が無かったので、「絵文字を送ることが出来る新しいメール送信クラスを作りたい」と思ったとします。


クラス名は「EmojiMail」クラスにしましょう。


その場合、新しく作る「EmojiMail」クラスに、先ほどMailクラスに書いた様々な処理をまた書くのは面倒くさいですよね。


こんな時に便利なのが「継承」です。


EmojiMailクラスを作る際に、親クラスとしてMailクラスを継承するように書くと、Mailクラスの持っている能力(データや処理一式)をそのまま引き継ぐことが出来ます。




同じ処理をもう一度書く必要はありません。


EmojiMailクラスに書くのは、親クラスが持っていない「絵文字を送る」という処理だけでOKです。


また、親クラスが持っている機能を上書きして書き換えることも出来ます。


例えば、メールを実際に送る「send」というメソッド(関数)があった場合に、Mailクラスでは通常のメールを送りますが、EmojiMailクラスでは絵文字に対応したメールを送るといった形です。



メリット②「使う側は呼び出し方を統一出来る」


このように定義しておくと、呼び出し側は「send」というメソッドを呼べば、インスタンス化したのがMailクラスなら「通常のメール」、インスタンス化したのがEmojiMailクラスなら「絵文字メール」を送ってくれます。




sendという統一した命令を行えば、それぞれのクラスに応じた動きをしてくれるという訳ですね。


ちなみに、このことを「ポリモーフィズム」と言ったりします。


これによって、クラスに機能の追加や修正があった場合にも、呼び出し側のコードをいちいち修正する必要がありません。



メリット③「外部に触らせる必要の無いデータは隠すことが出来る」


変数を煩雑に管理していると、何かの間違いで変数の内容が書き換えられてしまったりしてバグの元になります。


しかし、クラスの中に定義された変数(プロパティ)は、クラスの外部に見せるか見せないか、という設定を行うことが出来ます。




外部に見せない設定を行えば、そのプロパティはクラスの中だけで書き換えることができ、外から書き換えたい場合もクラスのメソッド経由で書き換える形になるため、より安全になります。


このことを「カプセル化」と言ったりします。



まとめ


以上、これらがオブジェクト指向を使うメリットになります。


変数や関数をばらばらに管理するのではなく、ある特定の役割を行う「もの(オブジェクト)」として定義することで便利に再利用出来たり、継承、ポリモーフィズム、カプセル化といった手法で、よりスマートで安全なコードを書くことが出来るという訳ですね。


ただ、自分の書いたソースコードの効率化を進めていくと、結果「オブジェクト指向的な考え方」になっていきます。ですので、最初から概念を頭で深く理解しようとするよりも、効率的でバグの少ないコードを書くことを意識していきましょう!


おすすめ記事