オブジェクト指向の悟りを開く!初心者でも分かるOOPの最重要技術ポリモーフィズムの使い方!

      2017/01/14

オブジェクト指向の三大要素は継承、カプセル化、ポリモーフィズムです。
中でもポリモーフィズムが最も強力かつ難解な技術と言われています。

Rubyの開発者まつもとゆきひろさんも「オブジェクト指向プログラミングを構成するテクニックのうち,ポリモーフィズムは最も重要なものと言えます。」と仰っています。
http://itpro.nikkeibp.co.jp/article/COLUMN/20050905/220607/

MSDNでも「ポリモーフィズムは、オブジェクト指向プログラミングにおいて最も重要な概念であるともいわれています。」とあります。
http://msdn.microsoft.com/ja-jp/library/cc482734.aspx

私も同意見です。

ポリモーフィズムを理解した時、悟りを開いたような「オブジェクト指向ってそういうことかぁ!!」と心から腑に落ちたのを覚えています。

ポリモーフィズムのよくある説明はAnimalクラスを継承したCatクラスの鳴くメソッドを呼び出すと「ニャ~」と鳴く、Dogクラスの場合、「ワン」と吠えるみたいな説明がよくありますが、このような説明では実際のプログラミングにどう使えばいいのかがわかりませんよね。この記事では実際に使える例を紹介します。

実際に役に立つポリモーフィズムを一言でいえば、「呼び出す側のコードを共通化する技術」です。

「なんじゃそりゃ?」と思われた方も安心してください。この記事は初心者でもポリモーフィズムが分かるような解説記事になっています。

重複のあるサンプルコードを手続き的なやり方とポリモーフィズムを使ったやり方で共通化していきます。そのアプローチの違いを見ることでポリモーフィズムを理解することが出来るはずです。

これを読めば、あなたもオブジェクト指向の「悟り」を開けます!

デザインパターンはポリモーフィズムのパターン

23個のデザインパターンの内Singleton、Facadeなどを除くほとんどのパターンはポリモーフィズムをどう使うかのパターンです。

ポリモーフィズムのパターンも大きく2つにわけることができます。Strategyパターン型かTemplate Methodパターン型です。

なので、StrategyパターンとTemplate Methodパターンを覚えれば、ポリモーフィズムを理解することができるんです。

おすすめ本は結城浩さんのJava言語で学ぶデザインパターン入門です。私はこの本を読んでポリモーフィズムを悟りました。

なので、この本を読めばいいんですけど、結構分厚い本なので読むのも大変です。この記事ではコンパクトにエッセンスを凝縮して解説します。

※ この本は分厚いけど、文章が分かりやすいので実際読むのはそれほど大変ではないのでぜひ読んでみてください。

重複したコードを共通化する方法は2種類

重複したコードを共通化する方法は多数ありますが、本質的には以下の2つに絞られると思います。

  1. 重複したコードをメソッド/関数に切り出して共通化する
  2. ポリモーフィズムで処理の流れを共通化する

あと、もう一つ入れるとすればAOPで前後処理を追加するっていうのがありますが、今回は省きます。

では次の2つのプログラムから重複ロジックを抽出し共通化を施してみましょう。
↓1つ目のプログラム

↓2つ目がこちら。とても似ているコードですが、少しだけ違います。つまりコードが重複しています。

どちらもファイルを読んで解析をして結果をファイルに出力するというプログラムです。ファイルオープンやクローズ、例外処理などが重複しています。

共通化を施すためのサンプルコードなのでわざと冗長な書き方をしている部分もありますが効果を分かりやすくするための演出なのでJavaをディスる主旨はありません。

1. 重複したコードをメソッド/関数に切り出して共通化する

まずは多くの人にとってなじみのある手続き型言語的なアプローチで共通化してみましょう。

重複したコードをメソッドに切り出します。ファイルをオープン・クローズするコードをメソッドに切り出してみましょう。

FileUtilという共通クラスにメソッドを切り出しました。このクラスを使うようにAppLogAnalyzerとWebLogAnalyzerを書き換えましょう。

重複コードが減って多少すっきりしましたが、try-catchのコードが重複しています。

手続き型言語的アプローチだとここまでが限界なのですが、オブジェクト指向言語の機能を使って、これらを共通化できないでしょうか?

やり方が思いつきませんか?

ここでポリモーフィズムの出番なのです。

2. ポリモーフィズムで処理の流れを共通化する

Javaでポリモーフィズムを使うためには抽象クラスかインターフェースを使います。このサンプルプログラムの場合、処理の流れに2つのパターンがあります。

パターン1
1. 読み込み用ファイルをオープンする
2. ファイルを読んでなんらかの集計処理をする
3. ファイルを閉じる
4. 例外発生時にはスタックトレースを出力する

パターン2
1. 出力用ファイルをオープンする
2. ファイルになんらかの集計結果を出力する
3. ファイルを閉じる

なんらかの~という部分以外は同じ流れになっていることが分かります。

そこでなんらかの処理をする部分を抽象メソッドとして抽出して、共通の処理の流れの中から、その抽象メソッドを呼び出すつくりにします。

抽象メソッドはサブクラスで実装するのでサブクラスが何かによって、「なんらかの処理」が具体的な処理に決まります。

このような設計をTemplate Methodパターンと言います。Template Methodパターンを使って共通化を施してみましょう!

このFileAnalyzerクラスをAppLogAnalyzerとWebLogAnalyzerに継承させて、抽象メソッド(何らかの処理だったもの)を具体化するために実装します。

FileAnalyzerのanalyzeFileメソッドで処理の全体フローを記述しています。フローの中で異なる部分を抽象メソッド呼び出しすることでサブクラスの固有処理に遷移します。

このプログラムの場合、全体の流れはいっしょなんだけど、集計ロジックが異なっています。AppLogAnalyzerがエラーと警告の件数をカウントしてるのに対してWebLogAnalyzerは会社情報ページのアクセス数をカウントしています。その固有ロジックを抽象メソッドに切り出しています。

手続き型のアプローチだと共通部分をメソッドに切り出していましたが、ポリモーフィズムを使う場合は固有部分を抽象メソッドに切り出します。

真逆のアプローチです。

これらは補完関係にあるのでどちらが偉いというわけではありません。処理の流れは似ているんだけど一部分だけ違うっていう場合はポリモーフィズムを使って処理の流れを共通化するアプローチが有効です。

単純に重複コードがある場合はそれらをメソッドに切り出して使用する手続き型のアプローチが有効です。

いわゆるフレームワークというものは必ずポリモーフィズムを使用しています。ライブラリは固有ロジックから呼び出されますが、フレームワークの場合、フレームワークが固有ロジックを呼び出します。

  • 呼び出される側のコードを共通化したのがライブラリ
  • 呼び出す側のコードを共通化したのがフレームワーク

なんです。

制御の反転(Inversion of Control、IoC)ってやつです。

ポリモーフィズムを使えば手続き型言語の数倍共通化できる!

いかがだったでしょうか?

ポリモーフィズムを使えば、重複ロジックをメソッドに切り出すよりも多くのコードを共通化できることがお分かりいただけたかと思います。

AppLogAnalyzerとWebLogAnalyzerを最初のバージョン、手続き型アプローチで共通化を施したバージョン、ポリモーフィズムで共通化を施したバージョンとで見比べてみてください。ポリモーフィズムバージョンのコードは驚くほど短くなっています。

AppLogAnalyzerは68行から36行へ、WebLogAnalyzerは64行から33行へと減っています。

処理の流れは似ているんだけど一部分だけ違うとか、例外をとらえる処理を共通化したい場合、ポリモーフィズムを使用するとうまくいきます。

もちろん、手続き型のアプローチが有効な場面も多々ありますから、適材適所で取り入れるのが良いです。

ここまで読んだ方は、オブジェクト指向の悟りを開けたかと思います!

「あんまりよく分からなかった」という方は基礎知識をじっくり学んだ方がいいかもしれません。最後に初心者がプログラミングを学ぶ際に使えるサービスを紹介します。

プログラミング初心者におすすめのサービス
1. 講師から対面で学びたい派なら

プログラマカレッジをおすすめします。ProEngineerという転職エージェントが運営しているプログラミングスクールです。20代限定なんですが、無料で受講できて、修了後、就職支援もしてくれるんです。最高過ぎですよ、これ!!就職の紹介料を企業からもらえるのでスクールを無料にできるんでしょうね。すばらしいシステムだと思います!

30代以上の方には

プログラマカレッジは20代限定なので30代以上の方にはWebCamp Proをおすすめします。受講料の返金保証がついているし、毎日11時〜23時まで通い放題なのでとてもいいと思います!

2. 自宅で学びたい派なら

「就職保証付き」オンライン就職予備校をおすすめします。Javaエンジニアコースでは就職保証がついているのでプログラマーとして就職したい方にはぴったりです。Javaエンジニアの求人ってめっちゃ多いし、求められる技術レベルもそこまで高くないのでちゃんとした教育プログラムなら就職保証できるだろうなとJavaエンジニア経験者の私も思います。

3. つまづいた時に質問したくなったら

プログラマー専用の質問サイトteratailをおすすめします。 つまづいた時にteratrailで質問すれば教えてもらえます。

これらのサービスを活用すれば、全くの初心者からでもプログラミングをばっちり出来るようになると思います!レッツトライです!

エージェントを使った方が転職活動は楽です

東京・大阪近郊のイケてるIT企業に転職したい人には『レバテックキャリア』

 東京・大阪近郊のエンジニア経験者向け転職サービスです。

このサービスを運営しているレバレジーズという会社はシステム開発もやっているので、現場の仕事をよくわかってくれてますし、ヒカ☆ラボというIT系の勉強会なども主催していたりteratailというプログラマー専用の質問サイトを運営してて好感が持てます。求人案件もWebやスマホの面白い仕事が多いのでいいと思います。

ホームページを見ると分かるんですが、若くて美人の担当者が多いのもナイスなんです!私の場合(たぶんあなたも)、担当者が美人だと転職活動のモチベーションめちゃ上がりますからね笑

エンジニア未経験の方や地方在住の方にはワークポートというエージェントをおすすめします。

エンジニア未経験の方や地方在住の方には『ワークポート』

全国の求人を扱っていて、しかもITエンジニア未経験の人にも転職支援をしてくれるエージェントです。

未経験の人はサポート対象外のエージェントが多い中、ワークポートは未経験者を支援し転職を成功させています。

未経験の方こそエージェントから職務経歴書の作り方や面接の仕方のレクチャーを受けた方がずっとうまくいきます。

『派遣社員』なら正社員とフリーランスの『良いとこ取り』!

  • 「フリーランスになりたいけど、確定申告とかめんどくさいな」
  • 「定時帰りできる職場や、時短勤務がしたい」

という方には派遣社員がおすすめです。

派遣ってネガティブなイメージありますが、ITエンジニアの派遣社員なら

  • 時給が高く、給料も悪くない
  • やりたい仕事を選べる
  • 確定申告不要(派遣会社がやってくれる)
  • 厚生年金、健康保険も派遣会社が入ってくれる

ので、正社員とフリーランスのいいとこ取りな、とてもいい選択なんです。

 - 勉強法