独り言

プログラミングの講師をしています。新人研修で扱う技術の解説と個人の技術メモ、技術書の紹介など

【プログラミング全般】オブジェクト指向入門

ここでは様々なプログラミング言語でサポートされているオブジェクト指向について解説します。
オブジェクト指向は一言でいえば、モノ(オブジェクト)に着目したプログラミングの概念で、開発を効率よく行うために必要な考え方です。
オブジェクト指向をサポートしている言語としては、Java, PHP, Ruby, Python, C#, VB .NETなどがあります。
これだけではなく、他のも多くの言語でサポートされています。
90年代以降の作成されたプログラミング言語オブジェクト指向をサポートされているものが多く、最近の言語を学ぶ場合には避けて通れない技術です。

プログラミングの歴史

オブジェクト指向の説明に入る前にざっくりとプログラミングの歴史を振り返ります。

  • 機械語の時代
    0と1の2パターンでプログラミングをしていた時代。
    コンピュータの専門家の人しかできない。

  • アセンブリ言語の時代
    記号、アルファベットが使えるようになって機械語よりはましになった時代。
    けど、まだ簡単とは言えず、一部の専門家の人がプログラミングしていた(らしい)。

  • 高級言語の時代
    COBOLとかFORTRANの時代。
    英語の文法に近くなってかなり分かりやすく書けるようになった時代。
    アセンブリに比べて敷居は下がったが、GOTO文が乱用されており、プログラムの規模が大きくなるとメンテナンスが難しい。

  • 構造化言語の時代
    C言語など。
    順次・分岐・繰り返しというアルゴリズムの3要素で処理の流れを表現する。
    GOTO文がなくなり、メンテナンス性向上。

  • オブジェクト指向言語の時代
    構造化言語では、データを保持するのにグローバル変数という仕組みが使われていた。
    しかし、グローバル変数が多くなると、どこでどの変数が使用されているのかが分かりにくく、メンテナンスが難しくなった。
    その問題を解決するために生まれたのがオブジェクト指向
    データと処理をオブジェクトという概念で1つにまとめることで、プログラミングをしやすく、規模が大きくなってもメンテナンスがしやすくなった。

  • フレームワーク・ライブラリの時代
    オブジェクト指向の開発をさらに効率よく行うために、プログラムを再利用する動きが広まった。
    それがライブラリとフレームワーク
    ライブラリは、他の人が作成したプログラムを使うことで、面倒な処理や複雑な処理を自分で1から作成する必要がなくなる。
    フレームワークは、プログラムの半完成品みたいなもので、決められたルールに基づいてコーディングをすることでソースコードを書く量を減らし、効率を上げる仕組みです。
    フレームワークやライブラリが登場する中で、オブジェクト指向でよく使われる設計のパターンが出てきました。
    そのパターンを体系的にまとめたのがデザインパターンです。
    デザインパターンオブジェクト指向の考えを活かすために設計思想で、ライブラリやフレームワークの中に多く登場します。

  • ローコード・ノーコードの時代
    プログラミング言語ソースコードをほとんど書かずにプログラミングができる技術が流行している。
    ローコードは、少ないコード量で開発ができる技術。
    ノーコードは、全くコードを書かずして開発ができる技術。
    GUI操作でシステムを構築することができるため、非エンジニアでも開発ができることで注目を浴びています。

オブジェクト指向を学ぶメリット

この記事を書いている2020年現在、ローコード・ノーコードが大きな注目を浴びていて、今後も拡大していくことが予想されます。
ノーコードでは、プログラミング言語を学ぶ必要すらないため、今後の動向によってはオブジェクト指向を学ぶ意味は薄れてくるかもしれません。
そうでなくても、プログラミング言語を使って開発する場合、フレームワークを活用した開発がほとんど。
オブジェクト指向の仕組みを理解していなくても開発ができてしまう時代でもあります。
そんな時代にオブジェクト指向を理解する必要は果たしてあるのでしょうか。

今後もしかするとオブジェクト指向を学ぶメリットはなくなってくる可能性はありますが、フレームワークによる開発が主流であるうちは、まだオブジェクト指向を学ぶ意味はあると考えます。
なぜなら、フレームワークの中ではオブジェクト指向の仕組みが多く使われているからです。
オブジェクト指向について深く理解することができれいれば、フレームワークやライブラリの中身を理解することもできます。
そうなれば、フレームワークやライブラリを使用している中でエラーが発生したとしても、自分の力で解決できる可能性が高くなります。
また、フレームワークを自分で開発したり、既存のフレームワークを拡張することも可能になります。
一方、オブジェクト指向について理解が浅いと、フレームワークでエラーが発生しても中の仕組みが分からず、自分の力だけで解決することが難しくなります。

フレームワークやライブラリを使いこなし、トラブル解決も早いプログラマーになるにはオブジェクト指向の理解は不可欠になります。

オブジェクト指向の用語

オブジェクト指向でよく使用される用語について解説します。

オブジェクト

オブジェクトは日本語だとモノという意味です。
パソコンやスマホ、ペットボトルや机、イスなど、人間が認識することができるものは全てオブジェクトと言えます。
目に見えるもの、見えないものでも構いません。
コンピュータだと、ログインしているユーザー、商品、投稿、キャラクター、武器、など、人間が識別できるものがオブジェクトです。
用は何でもありですが、プログラミングをするときに人間にとって扱いやすい単位をオブジェクトとして扱うのがオブジェクト指向プログラミングです。

クラス

オブジェクト指向を学ぶ上で必ず出てくるのがクラスという概念です。
クラスはオブジェクトの基となるものです。
オブジェクトの設計書と呼ばれることもあります。
また、オブジェクトを抽象化したもの、という考え方もできます。
例えば、普段使用しているスマホやPCは、物理的に実体のあるモノですが、「パソコン」や「スマホ」という言葉自体は、実体のあるものを指しているわけではなく、パソコン全体、スマホ全体を表すための概念です。
「人間」という言葉も、特定の誰かを示す言葉ではなく、人間全体を表す概念で、実体のある人間の1人として私やこれを読んでいるあなたという存在がいます。
このように、オブジェクトという具体的なものを抽象化したものがクラスです。
クラスは日本語だと分類という意味を持ちます。
(学校のクラスも分類という意味ですね。)
そのため具体的なオブジェクトを分類するものがクラスという風に考えるのも自然です。
例えば自分自身の存在を分類すると、人間、社会人、男性、などに分類することができます。
このような分類がクラスになります。

インスタンス

クラスと同じ頻度でよく登場する用語がインスタンスです。
インスタンスはクラスを元に作られるもので、オブジェクトとほぼ同義です。
厳密には微妙にニュアンスが異なるようで、オブジェクトの方が幅広いです。
インスタンスは、クラスを元に作られたものに限られます。
多くのオブジェクト指向プログラミング言語ではnewというキーワードを使用してクラスを元にしてインスタンスを作成します。

メソッドとプロパティ

プログラミングにオブジェクト指向の考え方が取り入れられることで何が便利になったのか。
オブジェクト指向以前の言語では、データの保存と処理の定義はそれぞれ切り離されていました。
処理は関数で定義され、データはグローバル変数に保持していました。
それをオブジェクトという単位でデータと処理をまとめることにより、わかりやすく、そして拡張しやすいプログラムを作ることができます。

オブジェクトの中で定義されている処理のことをメソッド、オブジェクトの中で定義されているデータのことをプロパティと呼びます。
プロパティは言語によって呼び方が異なることがあり、例えばJavaではフィールドと呼ばれます。

コンストラク

多くのプログラミング言語では、インスタンスを作成する時にnewというキーワードを使用します。
そしてインスタンスが作成された時に呼び出される特殊な処理を定義することができます。
このインスタンス生成時に呼び出される処理のことをコンストラクタと呼びます。
コンストラクタでは、主にプロパティの初期化の処理などを定義することが多いです。

オブジェクト指向 三大要素

オブジェクト指向にはオブジェクト指向の三大要素と呼ばれるものがあります。
それは

の3つです。
本によっては四大要素として、「抽象化」がプラスされていることもあります。
それぞれを簡単に解説します。

継承

継承は、特徴を受け継いでいくことをいいます。
例えば、「生き物」「哺乳類」「人間」「社会人」という4つのクラスがあったとします。
哺乳類は生き物に含まれます。
つまり、生き物の特徴を受け継いでいます。
生き物の特徴を受け継ぎつつも、哺乳類特有の機能を持っています。
人間は哺乳類に含まれます。
つまり、哺乳類の特徴を受け継ぎつつも、人間独自の機能や特徴を持っています。
社会人は、人間の中でも学生生活を終えて働き始めた人たちのことを挿します。
つまり、人間の特徴を持ちつつ、社会人にしかないステータスや行動をいいます。
この場合、哺乳類は生き物を継承し、人間は哺乳類を継承し、社会人は人間を継承していると言えます。

もう一つ例を出しましょう。
「乗り物」「車」「電気自動車」というクラスがあったとします。
車は乗り物に含まれます。
乗り物の特徴がありつつも、車独自の機能があります。
つまり、車は乗り物を継承しています。
電気自動車は車の特徴がありつつ、電気自動車独自の機能があります。
つまり、電気自動車は車を継承しています。

イメージとしては、継承される継承元の方が概念としては広く、継承先はより具体的になっていくようなイメージです。
継承のイメージができたでしょうか。

プログラミングに継承という概念が導入されると何が良いのでしょうか。
プログラミングでは、継承を使用することでソースコードの量を減らすことができます。

先に例に出した「人間」クラスと「社会人」クラスを考えます。
人間は年齢、名前、性別などがあります。
これらの情報を「人間」クラスに定義していたとします。
そして、人間クラスを継承した社会人クラスを作成したとします。
社会人も人間なので、年齢、名前、性別といった情報はありますが、それらの情報は人間クラスに定義されているので、社会人クラスでは改めて定義する必要がなくなります。
プログラムを書くときに、社会人だけに必要となる情報だけを追加していけばよくなります。
結果として、全体のコード量を減らすことができます。

オーバーライド

オーバーライドはオブジェクト指向の三大要素ではありませんが、継承と非常に深い関係がある概念のため、ここで説明しておきます。
オーバーライドは簡単にいえばメソッドの上書きです。
継承を使うと、親クラスに定義されているメソッドを無条件に使うことができますが、親クラスから受けついだメソッドを上書きすることが可能です。
このような仕組みのことをオーバーライドといいます。
この説明だけだと何のメリットがあるのかわからないと思いますが、後に説明するポリモーフィズムと非常に深い関わりを持ちます。

カプセル化

カプセル化は、オブジェクトが持つデータを外部から直接アクセスできないように隠蔽して、メソッドによってデータのアクセスを提供することです。
多くのプログラミング言語では、アクセス修飾子という仕組みがあります。
オブジェクトが持つプロパティやメソッドに対して、外部からどこまでアクセスを許可するかを設定するものですが、そのような仕組みを駆使してカプセル化を実現します。
説明だけでは理解しにくいかもしれません。
例えば人間は名前、年齢、などのデータを持ちますが、このようデータは他人が勝手に変えることはできません。
つまり、外部から勝手に変えることができないデータです。
現実世界では人の名前を他人が勝手に変更するなんてことはあり得ませんが、プログラムでオブジェクトを作成したとき、作り方によっては外部から簡単にデータを変更することができてしまいます。
そのような不都合が起きないようにする仕組みがカプセル化です。

ポリモーフィズム

ポリモーフィズムは日本語では多態性、多様性などと呼ばれます。
これは継承や抽象化を前提とした機能で、異なるオブジェクトを同一視して扱う機能です。
先に紹介したオーバーライドの機能があることで成り立つ非常に便利な機能です。

例えば、「プログラマークラス」と「営業クラス」があったとします。
プログラマーにプログラミングをして欲しい時には、プログラマークラスのオブジェクトを作成し、プログラミングをするメソッドを呼び出します。
営業に営業の仕事をして欲しかったら、営業クラスのオブジェクトを作成し、営業活動をするメソッドを呼び出します。
ただ、このプログラマーと営業の上司が同じ人だった場合、人によっていちいち指示する内容を変えるのは面倒ですね。
「働け」という同じ命令をすることで、プログラマーならプログラマーとしての働きを、営業なら営業としての働きをしてくれると便利です。
この仕組みを実現するのがポリモーフィズムです。
実際には「社員クラス」のようなクラスを作成し、「働く」メソッドを定義しておきます。
プログラマークラスと営業クラスは、社員クラスを継承し、働くメソッドをオーバーライドし、それぞれの働く内容を上書きします。
そうすると、社員に対して「働く」メソッドを実行してもらうと、そのオブジェクトがプログラマーならプログラマーとしての働きと、営業なら営業としての働きをしてくれるわけです。

メソッドや関数という概念は、呼び出される処理を共通化する仕組みですが、ポリモーフィズムは処理の呼び出しを共通化する仕組みだといえます。
文章の説明だけだと分かりにくいかと思いますが、ソースコードで確認する場合はJavaオブジェクト指向編の記事に書いているのでそちらを参照ください。

UML

UMLはUnified Modeling Languageの略で、オブジェクト指向の分析と設計をするときに使用するモデリング手法です。
いくつかの図(ダイアグラム)が用意されています。
よく使用するのはクラス図、シーケンス図、ユースケース図あたりでしょうか。
ここでは詳細は解説しません。
機会があれば別でUMLについての記事もまとめます。
クラス図はオブジェクト指向の理解を助けるのに重要な役割をはたしますので、クラス図については調べて理解しておくと良いでしょう。

まとめ

ソースコードがないと理解が難しい用語もあるかと思います。
Javaオブジェクト指向編の記事と合わせて読んでいただければと思います。

オブジェクト指向の理解を深めるおすすめ書籍