ポリモーフィズムとは?仕組みやメリット、デメリットを解説

昨今のプログラミングをおこなうにあたっては、オブジェクト指向型のプログラミングが主流になっています。

オブジェクト指向型プログラミングは、その内容を理解するのが難しいとされています。

そこで今回の記事ではポリモーフィズムといわれる考え方について解説します。

ポリモーフィズムを理解することで、オブジェクト指向プログラミングの深い理解につながっていきます。

ポリモーフィズムの仕組みや考え方を具体例に沿って解説し、メリットやデメリットについてもお伝えしたいと思います。

オブジェクト指向

ポリモーフィズムについて解説する前に、オブジェクト指向の概要について説明します。

オブジェクト指向とは、プログラミングをおこなう際の設計方法の考え方のことです。

ある特性を持ったモノを1つのグループとして捉え、そのグループ化したモノごとに様々な関係性を定義したり、同一の動作を組み込むなどしてプログラミング設計をおこないます。

オブジェクト指向を理解するために「血液型」を例に挙げます。

人にはそれぞれの個性があり、一人一人の性格や考え方をモレなく取り上げるのは困難です。

これを血液型に当てはめて、
「A型のタイプは〇〇、B型のタイプは〇〇」
というような枠組みでまとめて解釈するというのがオブジェクト指向のイメージです。

こうすることで、例えば人の動きをプログラムに記述する際、一人一人の動きを書くのではなく、血液型でグループ化して記述することができるため、シンプルなコードでプログラムの作成が可能になります。

このように、オブジェクト指向の目的は、いかに効率よく開発をおこなうか、ということに焦点が当てられています。

オブジェクト指向プログラミングを取り入れることで、プログラムをわかりやすくするだけでなく、保守性や拡張性、再利用性が高いものにすることが可能です。

一方で、オブジェクト指向は具体的な手順や手法をあらわしているのではなく、あくまでも概念や考え方のことをさすため、抽象的な内容になりがちで理解が難しいとされています。

オブジェクト指向を用いるにあたり、必ず理解しなければならない重要な要素として、「カプセル化」、「継承」、「ポリモーフィズム」があります。

ポリモーフィズムとは

ポリモーフィズムはオブジェクト指向プログラミングにおいて重要な概念です。

ポリモーフィズムは日本語で多様性という意味を有しています。

ポリモーフィズムとは、プログラムを記述する際に、同じ名前のメソッド(動作・挙動)や関数であっても、中身の違いによってそれぞれのオブジェクトに合わせた異なる動作をするというものです。

この考え方により、プログラムで同じ命令をおこなったとしても、それぞれが独立した固有の処理をおこなうことが可能になりました。

ポリモーフィズムを使うことで、コードの再利用性や保守性、拡張性が向上するだけでなく、新しいデータ型を追加する場合でも既存のコードを変更する必要がなくなったりと、柔軟なプログラミングの記述が可能です。

ポリモーフィズムの仕組みと具体例

ポリモーフィズムはあくまでも考え方や概念の話のため、ここまでの解説を見ても難しいと感じられたかもしれません。

ここからはポリモーフィズムの仕組みや実際の例を取り上げて解説します。

ポリモーフィズムの仕組み

ポリモーフィズムの仕組みを理解するためには、「継承」の知識が必要です。

継承とは、同じようなプログラムをまとめることでコードを再利用しやすくする仕組みです。

大規模なプログラムの場合、コードが見づらくなったり、読みづらくなったりします。

その原因として、同じような機能をもつコードを重複して記述するからです。

重複したコードを書くことによってミスが増え、思わぬバグやトラブルを起こしてしまう可能性があり、メンテナンスが難しくなります。

また、メンテナンスが難しくなることによって、機能追加などの改修作業も比例して難しくなるため、システムの拡張性が下がってしまいます。

継承という概念を運用に取り入れることで、同じようなプログラムをまとめて共通化をはかることが可能です。

しかし、継承ばかりだと同じ挙動をするプログラムしか作成できないという欠点があります。

この問題を解消するために、共通化したコードは残しつつも、異なる挙動にしたい部分を目的に合わせて変えられるようにしたのがポリモーフィズムです。

ポリモーフィズムは、複数の異なるオブジェクトに対して同じ指示命令をおこなうと、それぞれのオブジェクトに対し異なる挙動を実行させることができるという仕組みになっています。

ポリモーフィズムの具体例

ポリモーフィズムの具体例を紹介します。

人間には「挨拶」という言葉があります。

しかし、単に挨拶と言っても、
日本であれば「こんにちは」
アメリカなら「ハロー」
中国なら「ニーハオ」
など、挨拶にも様々な種類があります。

これらの挨拶という挙動をプログラムに実装する場合、それぞれの国、それぞれの言葉を記述するのは手間になるだけでなく、修正が発生した場合などは一個一個のコードを変更しなければなりません。

ポリモーフィズムを取り入れた場合、「挨拶」という処理を実行すると、指示を受け取ったオブジェクトはそれぞれ異なる挨拶(こんにちは・ハロー・ニーハオ)をする、という挙動になります。

このように、ポリモーフィズムを実装することで、同じ指示命令でもそれぞれのオブジェクトが最も適した挙動をおこなうことが可能になります。

ポリモーフィズムを意識してメソッドを作ると

では、具体的にプログラムのソースで見ていきましょう。

下記は、PHPでポリモーフィズムを実現する際のコードです。

interface Shape {
    public function getArea(): float;
}

class Circle implements Shape {
    private $radius;
    public function __construct($radius) {
        $this->radius = $radius;
    }
    public function getArea(): float {
        return pi() * $this->radius * $this->radius;
    }
}

class Rectangle implements Shape {
    private $width;
    private $height;
    public function __construct($width, $height) {
        $this->width = $width;
        $this->height = $height;
    }
    public function getArea(): float {
        return $this->width * $this->height;
    }
}

$shapes = [ new Circle(2.0), new Rectangle(3.0, 4.0) ];

foreach ($shapes as $shape) {
    echo $shape->getArea() . “\n”;
}

上記は、ShapeをCircleとRectangleというクラスで継承しています。

そして、同じgetAreaという面積を求めるメソッドを呼び出しても、それぞれがオーバーライドして別々の計算をしているので、違った答えが返ってきます。

これが、前述した
「同じ指示命令でも、それぞれのオブジェクトが最も適した挙動をおこなうことが可能になる」
ということです。

ポリモーフィズムのメリット

理解習得の難易度が高いポリモーフィズムですが、数多くのメリットがあります。

1つ目のメリットは、柔軟性の高いプログラム設計が可能になることです。

ポリモーフィズムは、同じメソッドを異なるオブジェクトに対して適用することで、異なる動作を実現することができます。

このため、プログラムの設計において異なるオブジェクトを扱う場合にも、定義を共通化することで柔軟な設計が可能になります。

2つ目のメリットは、再利用性の高いコードを作成可能なことです。

ポリモーフィズムは、オブジェクト指向プログラミングにおいて、コードの再利用性を高めることができます。

同じルールを実装した異なるオブジェクトがある場合、共通のコードを再利用することができるため、開発効率の向上につなげることができます。

3つ目のメリットは、メンテナンス性の高いコードを作成可能なことです。

ポリモーフィズムはプログラムの修正や変更に対して柔軟な対応が可能となります。

例えば、新しいオブジェクトを追加した場合にも、共通化した部分の実装をおこなうだけで既存のコードに手を加える必要はありません。

そのため、メンテナンス性の高いコードを実現することができます。

4つ目のメリットは、可読性の高いコードを作成可能なことです。

ポリモーフィズムはコードの共通化を実現することができるため、コードがシンプルで可読性の高いものになります。

コードの処理内容を容易に理解できるようになるため、属人化の解消にもつながります。

ポリモーフィズムの利用例

以上のメリットを踏まえ、ポリモーフィズムは主に以下のような状況下で使われます。

1つ目のケースは汎用的な処理を実現したい場合です。

ポリモーフィズムは複数のオブジェクトに共通する動きを抽象化し、汎用的な処理を実現するために使用されます。

例えば、先に述べた各国の挨拶をする機能を実装する場合、国(親クラス)に対しての挨拶(メソッド)を記述するのではなく、各国(子クラス)の挨拶(メソッド)で上書きするオーバーライドすることで汎用的な機能を実現できます。

2つ目のケースは柔軟な拡張性が求められる場合です。

ポリモーフィズムはシステムの要件が変更された場合でも、影響を最小限に抑えることができます。

例えば、あるクラスを利用する別の定義が追加された場合でも、既存のコードに大きな変更を加えることなく新しい定義を利用することが可能です。

3つ目のケースは変数の型を抽象化する必要がある場合です。

ポリモーフィズムは変数の型を抽象化して、異なる定義のオブジェクトを同じモノとして扱うことができるため、コードの可読性や保守性を向上することができます。

例えば、あるメソッドにより複数のオブジェクトを受け取る必要がある場合、それらのオブジェクトが異なる型であっても同じ型として扱うことができます。

4つ目のケースはコードの再利用性が求められる場合です。

ポリモーフィズムは、オブジェクト指向プログラミングの中心的なコンセプトである再利用性を高めるために使用されます。

例えば、あるクラスを継承して新しいクラスを作成する場合、継承元のクラスに定義されたメソッドをそのまま利用することができます。

ポリモーフィズムのデメリット

一方でポリモーフィズムにはデメリットもあります。

1つ目のデメリットはパフォーマンス低下の可能性があることです。

ポリモーフィズムには、動的バインディングという仕組みがあります。

これは、メソッドを実行する際にどのメソッドが呼ばれるかわからないというものです。

この事象を解消するために、実行時にどのメソッドの呼び出しをするのか探索をするという処理が裏でおこなわれます。

これによりコードの実行速度が低下する可能性があります。

2つ目のデメリットはオーバーヘッドの増加です。

オーバーヘッドとは、何かのプログラムを実行する際に付随する処理のことをいい、システム負荷の要因となり得るものです。

ポリモーフィズムによってオブジェクトの動作を共通定義することができますが、それによりオーバーヘッドが発生する可能性があります。

ポリモーフィズムの実装箇所を限定的にするなど、処理の最適化を図ることが求められます。

3つ目のデメリットは設計の複雑化です。

ポリモーフィズムを導入することで、プログラムの設計が複雑になることがあります。

例えば、異なるオブジェクトに対して共通定義を設ける必要があるため、クラスごとの階層設計などにおいて工夫が必要となります。

設計時には十分な検討をおこなわなければなりません。

最適なシステム設計はAMELAに

今回は、オブジェクト指向プログラミングの特徴の1つである「ポリモーフィズム」を見てきました。

概念としては難しく感じるかもしれませんが、実際にプログラムを作っていくと、
「確かにこの方が効率的かも」
と感じられるでしょう。

AMELAでは、オフショア開発によって、海外の優秀なエンジニアによる開発が可能です。

既存のシステムの改修や機能追加、新規システムの作成など。

様々な実績がございます。

是非、一度ご相談頂ければと思います。