#初学者向けの記事です
はじめまして、プログラミング学習歴1ヶ月の新参者です。
Progateとかドットインストールで基本的なところを学習して、
クラス宣言などのコードは何となく書けるようになったものの、
いざオブジェクト指向って何?オブジェクトとどうちがうの?
クラスとインスタンスを説明してとなると言語化が難しい
っていうレベルの人向けに調べたことを書いていきます。
##<目次>
-
オブジェクト指向(OOP)とは
- OOPはなぜ重要なのか
- OOPのメリットとは
- 小ネタ スティーブ・ジョブズとOOP
- OOPっていったい何?
-
2種類のオブジェクト指向とは
- クラス型オブジェクト指向の特徴
- プロトタイプ型オブジェクト指向の特徴
- ふたつの違い
- 小ネタ JavaScriptは変わり種
-
コードを書きながら各用語について理解する
- 車の設計図からプリウスとレクサスを作る
- オブジェクト、プロパティ、メソッドとは
- クラス、コンストラクター、インスタンスとは
- 3つの言葉の抽象度
-
まとめ
-
参考資料
##<OOPはなぜ重要なのか>
オブジェクト指向(OOP)について調べていく上で、ある言葉に出会いました。
JavaScriptを理解するとは、オブジェクト指向を理解することだ
つまり、OOPを理解できれば JavaScriptを使いこなせるという意味ですが、この言葉の背景には何があるんでしょうか。
###オブジェクト指向の生みの親
1972年〜1980年にsmalltalkというプログラミング言語を公開したアラン・ケイが、その言語の説明のためにオブジェクト指向という言葉を生み出しました。そしてその後オブジェクト指向を元に多数の言語が作られました。C++やPython、JavaやRubyそしてJavaScriptなどです。これらはOOPという共通の考え方を持っています。だからこそJavaScriptを理解するとはオブジェクト指向を理解することだと言われているわけです。OOPは多数の言語が共通して持つ考え方ですから、いわばこれは前提知識です。理解しておけば他の言語の学習にも役立ちます。
###OOPのメリット
なぜ多くの言語でOOPが使われているのか、それはひとえに変更に対して柔軟に対応できるからです。スマホのアプリやOSなどもよくアップデートされていますが、一度組んだプログラムはバグの修正や更新をする必要があります。メンテナンスのために変更を加えたい部分だけを抜き出すことができるという性質が変更への対応のしやすさに繋がっています。そして変更したくない部分は触らずにメンテナンスできるということは、保守性にも優れてるということです。メンテナンスと保守性の両方のバランスが優れているということがオブジェクト指向型プログラミング言語の特徴です。
####小ネタ:スティーブ・ジョブズとOOP
ちなみに、アラン・ケイが指揮をとって開発したSmalltalkの環境で動くAltoというコンピュータがあるんですが、それに影響を受けたのが当時20代のスティーブ・ジョブズです。このAltoというコンピュータを見学したことがのちのmacの開発に繋がったというエピソードがあります。
##OOPっていったい何?
オブジェクトとは「モノ」という意味です。オブジェクト指向というのはものづくりの考え方で、モノが共通して持つ特徴を捉えて、それをプログラミングで表現して問題を解決していこうという考え方のことを言います。例えるなら設計図です。設計図にはデータや機能が書かれています。それらをコンストラクターやプロパティ、メソッドと言ったものを使い表現するのですが、これはそれぞれの言葉の意味を説明するよりもみた方がイメージを掴みやすいので、後ほど説明していきます。
##2種類のオブジェクト指向
オブジェクト指向には大きく分けて2種類あります。クラス型オブジェクト指向とプロトタイプ型オブジェクト指向です。それぞれの特徴と二つの違いをなんとなく頭に入れておいてください。
###クラス型オブジェクト指向
クラス型のオブジェクト指向の特徴は、設計図にクラスを使用します。そして親クラスである設計図の内容をすべて引き継いだ設計図である子クラスを作ることができます。これを継承といいます。さらに、子クラスに親クラスにはない新しいデータを追加したり、親クラスの持っていたメソッドを上書き(オーバーライド)することができます。
###プロタイプ型オブジェクト指向
プロトタイプ型オブジェクト指向の特徴は、設計図にプロトタイプを使用します。そしてそのプロトタイプを複製して新しいオブジェクトを生成します
###ちがいは何?
二つの大きな違いはクラス型のオブジェクト指向は後から設計図を変更することができませんが、プロトタイプ型は後からでも設計図を変更できるという点にあります。
クラス型のオブジェクト指向でも、後から設計図を変更することは現実では可能ではあるものの、適した使い方ではありません。子クラスが親クラスの内容を引き継いでいて、二つの間に関係性が生まれていますので、後から親クラスの内容を変更してしまうと子クラスにまで影響が及んでしまうため、親クラスの変更は極力避けたほうがいいでしょう。基本的には親クラスから子クラスへは単純→複雑 抽象→具体といった作り方が適しています。
###小ネタ:JavaScriptは変わり種
ところで、JavaScriptはクラス型かプロトタイプ型のどちらだと思いますか?
Progateなどをある程度やっている方はクラス型だと思うかもしれませんが、JavaScriptはプロトタイプ型です。人気のある他言語のほとんどがクラス型のオブジェクト指向であり、プロトタイプ型の馴染みがないので、2015年のES6からJSにもclass構文が追加されました。そのためクラス型のオブジェクト指向言語と変わらなくなりました。しかし、それ以前からもともとプロトタイプ型の言語の中でも異端の存在で、他のプロトタイプ型の言語が持っていないnew演算子やprototypeオブジェクトというものを持っていました。詳しい説明は省きますが、JavaScriptは元々はプロトタイプ型のオブジェクト指向言語ではあったものの、実際にはクラス型のオブジェクト指向言語に近い書き方をしなければならなかったのです。
##コードを書きながら各用語について理解する
それでは実際に設計図を作りコードを書いていきましょう。まずは車をオブジェクト捉えるならば、以下のような設計図を作りました。
オブジェクト名:車
プロパティ:車の名前、最高速度
メソッド:前に進む
###車の設計図からプリウスとレクサスを作る
この設計図からプリウスとレクサスを作っていきます。
後ほど解説しますが、これをインスタンスを生成するといいます。
プロパティ:車の名前:プリウス,最高速度:180km
メソッド:前に進む
プロパティ:車の名前:レクサス,最高速度:250km
メソッド:前に進む
###オブジェクト、プロパティ、メソッドとは
車というオブジェクトの中身にプロパティとして車の名前と最高速度、メソッドとして前に進むというものがありますが、それについて説明します。
オブジェクトとはプロパティの集まりです。そしてプロパティはプロパティ名と値で成り立っています。先ほどの例では出しませんでしたが、タイヤはハンドル、車体の色や重さなどもプロパティとして設定することができます。また、例えば車が「走行している」と言った状態もプロパティに含まれます。
次にメソッドですが、メソッドとは値に関数をもつプロパティのことです。前に進む、後ろに進む、左右に曲がると言った車の機能に加えて、電気で走る。自動運転と言った最近の流行りの機能もメソッドになります。
###コードで書いてみよう
では、実際にこれをプログラミングで表現していきます。今回はクラス構文を使って書いていきます。
まず、力技で書くとこうなります。
// 車名プリウス 最高速度180km 機能:前に進む
// 車名レクサス 最高速度250km 機能:前に進む
console.log('プリウスの最高時速は180km');
console.log('プリウスの機能は前に進む');
console.log('レクサスの最高時速は180km');
console.log('レクサスの機能は前に進む');
//実行結果
//プリウスの最高時速は180km
//プリウスの機能は前に進む
//レクサスの最高時速は180km
//レクサスの機能は前に進む
これは2台ならいいが1000台10000台となると大変だし、変更もしずらくなっています。
なので、class宣言を使って書いていきます。
// 車名プリウス 最高速度180km 機能:前に進む
// 車名レクサス 最高速度250km 機能:前に進む
//クラス名Carの先頭の文字は慣例的に大文字にします。
class Car{
constructor(){
this.name = '';
this.maxspeed = 0;
}
goForward(){
console.log('前に進む');
}
}
//インスタンスを生成する
let prius = new Car();
prius.name = 'プリウス';
prius.maxspeed = 180;
console.log(prius.name + 'の最高速度は' + prius.maxspeed + 'kmです');
prius.goForward();
let lexus = new Car();
lexus.name = 'レクサス';
lexus.maxspeed = 250;
console.log(lexus.name + 'の最高速度は' + lexus.maxspeed + 'kmです');
lexus.goForward();
//実行結果
//プリウスの最高時速は180kmです
//プリウスの機能は前に進む
//レクサスの最高時速は180kmです
//レクサスの機能は前に進む
###クラス、コンストラクター、インスタンスとは
ここで出てきたクラス、コンストラクター、インスタンスの説明をしておきます。
クラスはオブジェクトを生み出すための設計図です。データ(プロパティ)とデータに関連した振る舞い(メソッド)をもちます。
コンストラクターというのは関数です。new演算子でインスタンスが生成された瞬間に実行されています。クラス内で1度しか使うことができません。
インスタンスというのは実体のことで、クラスから生成されたオブジェクトのことをさします。設計図を元に作った具体的なモノということです。先ほどの例でいうとプリウスとかレクサスを作ることをインスタンスを生成すると言います。
###コンストラクターに引数を持たせるとさらに簡潔に書ける
コンストラクターは関数ですので、引数を持たせることができます。インスタンスを生成する際にclassに引数を渡すことでより簡潔なコードが書けます。
// 車名プリウス 最高速度180km 機能:前に進む
// 車名レクサス 最高速度250km 機能:前に進む
class Car{
constructor(name,maxspeed){
this.name = name
this.maxspeed = maxspeed
}
tellCar(){
console.log(this.name + 'の最高速度は' + this.maxspeed + 'kmです')
}
goForward(){
console.log('前に進む');
}
}
let prius = new Car('プリウス',180);
prius.tellCar();
prius.goForward();
let lexus = new Car('レクサス',250);
lexus.tellCar();
lexus.goForward();
//実行結果
//プリウスの最高時速は180kmです。
//プリウスの機能は前に進む
//レクサスの最高時速は250kmです。
//レクサスの機能は前に進む
##オブジェクトとクラスとインスタンスという3つの言葉の抽象度
この3つの中ではオブジェクトが最も抽象的です。クラスは設計図ですと説明しましたが、設計図もモノなのでオブジェクトであると言えます。インスタンスはクラスから生み出された実体ですが、これも当然オブジェクトです。
車というオブジェクト→車の設計図(クラス)→プリウス、レクサス(インスタンス)という順に抽象度が下がり具体的になっています。
##まとめ
- オブジェクト指向を理解しておくと、多数の言語の理解に役立つ
- メンテナンスと保守性のバランスに優れている
- オブジェクト指向とはものづくりの考え方
- クラス型とプロトタイプ型の二種類がある。
Everything is an object.(全てはオブジェクトである)
冒頭で紹介したアラン・ケイはオブジェクト指向のコンセプトを6つに要約して説明しました。その1文目がEverything is an objectという言葉です。つまり、オブジェクトひいてはオブジェクト指向の汎用性の高さを表す1文になっています。
最後までお付き合いくださりありがとうございました。
##参考資料
オブジェクト指向
オブジェクト指向と10年戦ってわかったこと
何となくjavascriptを書いていた人が一歩先に進むための本
これから学ぶjavascript