プログラミング言語において、関数やメソッド、変数など、型の概念を持ったさまざまな要素が、複数の型に属することができる性質のことです。
普通の変数や関数、オブジェクトなどは1つの型だけを持ちます。たとえば、int型として宣言された変数が、あるとき bool型に変わるということはありませんし、int型の引数を受け取る関数が文字列型を受け取るように変化することもありません。
多態性を持っている場合、いくつかの別々の型に属するかのような挙動を取ることができます。
たとえば、オブジェクト指向プログラミング言語において、引数がクラスA 型である関数f には、A のオブジェクトだけでなく、A を継承した B というクラスのオブジェクトを渡すこともできます。ここで、A の仮想メソッドを B がオーバーライドしていると、関数f は1つの実装しかないのにも関わらず、状況に応じて(渡されてきた引数の型に応じて)、異なる処理を呼び出すことができます。以下は架空のプログラミング言語の例です。
class A {
virtual void x() {
"A.x";
puts }
};
class B : A {
override void x() {
"B.x";
puts }
};
void f(A a) {
.x(); // a の実際の型に応じて、A.x() や B.x() を呼び分ける
a}
(new A()); // OK
f(new B()); // OK f
多態性の例として、このような仮想メソッドとオーバーライドによるものがよく登場しますが、実際のところ、多態性はオブジェクト指向の機能というわけではありません。ほかに、オーバーロードによるものや、ジェネリクス(C++ でいうテンプレート)によるものなどがあります。オーバーロードやジェネリクスによる方法は一般的には静的な多態性(静的ポリモルフィズム)を実現し、オーバーライドによる方法は動的な多態性(動的ポリモルフィズム)を実現します。
オーバーロードは、同じ名前の複数の関数を定義できる機能です。これは、1つの関数が、異なる型の引数に対して、異なる実装を持っていると考えられます(プログラミング言語の文法上、それぞれ異なる関数を定義しているようにみえるものが多いが、呼び出し側からみれば1つの関数にみえる)。
void f(int a); // 関数f の int型バージョン
void f(string a); // 関数f の string型バージョン
(100); // OK. int型バージョンを呼び出す
f("xyz"); // OK. string型バージョンを呼び出す f
ジェネリクスは、型を限定せずにソースコードを記述し、使用するときに型を特定します。以下は関数の例です。
void f<T>(T a); // T は呼び出し型で決める
(100); // OK. T は int型
f("xyz"); // OK. T は string型 f
仮に付けた T という名前の型を、具体的な型で置き換えたとき、関数f
の実装に文法上の問題がないかぎり、いかなる型にでも適用することができます(たとえば、T型の引数に対して
b = a / 2;
のような除算をするコードが含まれていたら、T を
string型に置き換えると /
に意味が与えられないため、問題があると思われる)。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |