目次
はじめに
オブジェクト指向という言葉を聞いたことがあるでしょうか。
プログラミングを学習していると遅かれ早かれ耳にする用語ですね。
オブジェクト指向については、概念的なものであるためか理解するのにちょっと手間取る方が多いようです。
この記事では、初心者の方にもわかりやすいように噛み砕いてオブジェクト指向について解説します。
オブジェクト指向の理解する一助になれば幸いです。
プログラミング言語の分類
まず、プログラミング言語は、プログラミングの考え方や記述方法によっていくつかに分類されます。
主なものでは手続き型言語、命令型言語、関数型言語、論理型言語などがあり、その分類の1つがオブジェクト指向言語です。
ここに挙げた中で従来比較的ポピュラーだったのが手続き型言語で、その代表例にC言語があります。
その他の言語については説明を省略しますが、オブジェクト指向言語はこの手続き型言語の欠点を補える点で注目を集めました。よく挙げられる代表言語例はJavaです。
ここからは、わかりやすさのために手続き型言語と比較しながらオブジェクト指向言語について解説していきます。
手続き型言語 vs オブジェクト指向
オブジェクト指向言語とは、簡単にいうと「処理対象をオブジェクトと呼ばれる単位に分割しオブジェクト同士のやりとりとして処理を記述する」ものです。
この説明ではいまいちピンときませんよね。
比較対象としてわかりやすい手続き型言語と比べながらどういうことか見ていきましょう。
ここでは、簡単なコード例として動物(犬、猫、鳥)を順番に鳴かせるプログラムを書いてみます。細かい文法は気にしなくてかまいませんので、雰囲気を味わってください。
手続き型言語(例:C言語)の場合
まず、手続き型言語はその名の通りコンピューターに実行してもらいたい手続きを上から順に書き連ねていく形式です。
#include <stdio.h> void dog_speak(void) { printf("ワンワン/n"); return; } void cat_speak(void) { printf("ニャンニャン/n"); return; } void bird_speak(void) { printf("ピヨピヨ/n"); return; } int main(void) { dog_speak(); cat_speak(); bird_speak(); return 0; }
C言語では必ず「main」という関数が実行されます。
main関数の前にそれぞれdog_speak、cat_speak、bird_speakの関数があってそれぞれ鳴き声を表示させる機能をもっており、main関数からこれらの関数が呼び出されていることに注目してください。
このように、手続き型言語では必要な手続きが上から順に書かれていて実行されます。
オブジェクト指向言語(例:Java)の場合
それではオブジェクト指向言語の場合はどうでしょうか。
public class Main { public static void main(String[] args) { Dog dog1 = new Dog(); Cat cat1 = new Cat(); Bird bird1 = new Bird(); dog1.speak(); cat1.speak(); bird1.speak(); } } class Animal { private String voice = null; public void setVoice(String str) { this.voice = str; } public void speak() { System.out.println(voice); } } class Dog extends Animal { public Dog(String str) { super.setVoice("ワンワン"); } } class Cat extends Animal { public Cat() { super.setVoice("ニャンニャン"); } } class Bird extends Animal { public Bird() { super.setVoice("ピヨピヨ"); } }
「なんだか、ややこしくなったなぁ…」と思われたかもしれません。
しかしこれは後述するオブジェクト指向のメリットを享受するためのひと手間なのです。
オブジェクト指向では、コードにもあるように犬、猫、鳥といった処理単位を「クラス(class)」として記述します。
このクラスから犬、猫、鳥のオブジェクトを生成(3、4、5行目)し、鳴かせる処理(speak)を呼び出していますね。
この部分は関数として実装していた手続き型言語との一番の違いはここです。
違いはわかったけれど、書き方が異なるだけで結局同じではないか?と思われるでしょう。
ここからはオブジェクト指向だとどんないいことがあるのかを解説していきます。
オブジェクト指向のメリット
オブジェクト指向のプログラミング言語では次のような3大メリットがあります。
これらの用語はオブジェクト指向の教科書にも必ず出てきますので、この機会にぜひ覚えてください。
継承
さきほどのJavaコードにAnimalというクラスがあったのに気づいたでしょうか。
気づかなかった方は、戻って見てみてください。
そして犬(Dog)、猫(Cat)、鳥(Bird)の各クラスは下記のような形で宣言されており、これを「Animalクラスを継承している」というふうに呼びます。
class Dog extends Animal { … }
Animalクラスには鳴き声を表す「voice」と、鳴かせる処理を表す「speak」が宣言されています。
一方、Dog・Cat・Birdsにはこれらがありません。
「鳴き声があって、それを鳴かせる」というやりたいことが共通しているため、ひとくくりにした「動物クラス(Animal)」の中で記述し、各動物はこれらの機能を継承して使えるようにしているわけです。
こうすれば、各動物のクラスではそれぞれに特化した内容だけを記述し、共通する内容はAnimalクラスに集約することができます。
今後別の機能(走る・食べる・遊ぶ等)を追加したり、今回の鳴く機能に修正を入れたりしたい時に一つのクラスだけを編集すればいいため管理が非常にしやすくなるのが利点です。
カプセル化
Animalクラス内の鳴き声「voice」の宣言の頭に「private」という単語がついています。
「setVoice」には「public」がついていますね。
これは、外部から呼び出したり変更したりできるかどうかを表しています。
コード例を見たほうがわかりやすいため、下記を見てください。
Cat cat2 = new Cat(); //2匹目の猫オブジェクトを生成 cat2.speak(); // ニャンニャン // ここで、鳴き声を変えてみる cat2.voice = "ゴロニャン"; //voiceがprivateなのでエラー cat2.setVoice("ゴロニャン"); //setVoiceはpublicなので成功 cat2.speak(); // ゴロニャン
このように、鳴き声(voice)に直接アクセスして勝手に変更しようとするとprivateであるためエラーとなります。
しかるべき操作方法として用意されたsetVoiceならばpublicなので成功することに注目してください。
結局外部から変更できてしまうんだから意味がないのでは?と思われたかもしれません。
しかし、例えばsetVoiceの処理の中に「いつ、どんなタイミングでvoiceが変更されたのかログに記録する」といったことを追加しておくことができます。
このように、外部からむやみやたらに変更できないようにすることをカプセル化と呼び、予期せぬバグを軽減できるのが利点です。
ポリモーフィズム
聞き慣れない言葉かもしれませんが、ポリモーフィズムとは多態性という意味です。
Javaの方では、犬・猫・鳥とも「speak」を呼び出すことで鳴かせることができました。
かたや手続き型言語であるC言語の方では、犬ならば「dog_speak」、猫ならば「cat_speak」という風に動物によって関数名が異なっていました。
例えばここに他の種類の犬や猫、また猿・狐・牛・馬…と様々な動物が追加されていくとしたらどうでしょうか。
動物の数だけ関数を用意し、かつその関数名を間違えないようにしっかり気をつけながらコーディングしないといけません。
オブジェクト指向言語ならば、例えばなんの動物かもはやわからないオブジェクトが100個(obj1、obj2、…、obj100)ある時ですら一律「.speak();」で処理を呼び出せば鳴かせることができます。
このようにある処理の呼び出し方を統一し、オブジェクトごとに異なる処理をさせることをポリモーフィズムといい、整合性の取れたコードが書けるのが利点です。
まとめ
オブジェクト指向について、手続き型言語との違いを交えながら解説しました。
ここで紹介したJavaに加え、C++・JavaScript・Python・Ruby等もオブジェクト指向言語です。
使ってみるのが一番早く理解できますので、ぜひチャレンジしてみてくださいね。
動画でプログラミング入門をしよう
オンライン学習サービスProglus(プログラス)でプログラミングを学び、創れる人になろう!
プレミアムプランを2週間無料体験しよう
今すぐ詳細を確認する