利用者定義演算子
利用者定義演算子 (りようしゃていぎえんざんし ) とはプログラミング言語において、言語の利用者が演算子に対し組み込みの演算子とは異なる動作を定義できる機能である。
古くはFORTRANから導入された機能である。当初は可読性と記述性の観点から各種言語に取り入れられた機能であるが、SmalltalkとC++によるオブジェクト指向の発達とともに多態性を実現するための機能としての側面も持つようになった。利用者定義演算子の定義はどのような言語でも関数またはメンバー関数あるいはメソッドのいずれかで定義するようになっている。
Smalltalkによる例:
Object
Value
Value methodsFor: 'accessing'
species
" '+' 演算子と '-' 演算子の定義。 "
Value methodsFor: 'operator'
+ aNumber
- aNumber
Value methodsFor: 'instance creation'
with: aNumber
value1 := Value with: 10.
value2 := Value with: 5.
" 利用者定義演算子を使用したため各変数には整数オブジェクトではなくValueクラスのオブジェクトが代入されている。 "
value0 := value1 + value2.
value0 := value1 - value2.
Smalltalkにおいてはメソッドに記号だけで構成されるセレクターをつけることで利用者定義演算子を定義することができる。Smalltalkでは演算子を2項セレクターとよびcodice_1など英数でできたセレクターとほぼ同様に扱う。Smalltalkにおいて演算子はメッセージの一種という扱いであり引数が必ず1個で優先順位が異なる点以外は特別扱いはしない。このため演算子として定義できる記号には殆ど制限がない(ただし区切り用の記号や代入記号は指定できない)。また、演算子として定義する記号は2文字でもよくcodice_2やcodice_3といった演算子がよく定義されている。Smalltalkは多重定義ができないため一つのクラスに同じ演算子を複数定義することはできない。ただし、インスタンスオブジェクトとクラスオブジェクトは同じクラスに紐づくものの別のオブジェクトであるためインスタンスメソッドとクラスメソッドで同じ演算子を定義することが可能になっている。
C++による例:
class Value
public:
// 大域関数版演算子の定義。
Value operator + ( int left, Value const &right )
Value operator - ( int left, Value const &right )
int main(void)
C++においてはcodice_4キーワードの後に記号をつけた形の特殊な名前を持つ関数を定義することで演算子を定義できる。C++では言語機能として用意されている演算子しか定義できず独自の記号を用いた演算子を定義することはできない。また、演算子の引数や戻り値の型は演算子の種類によって制限される。例えば型のメンバーを指定するcodice_2演算子を単項演算子として独自に定義したり、数値型やcodice_2演算子を定義していない型を戻り値の型として指定することはできない。多くの制限があるなか下記のような通常の関数と異なる演算子独自の振る舞いをする演算子があり通常の関数では不可能な構文を記述することができるようになっている。Smalltalkでは2項演算子しか定義することはできないがcodice_7 codice_8といった単項演算子は勿論codice_9といった添字演算子やcodice_10といった関数呼出演算子なども定義することができる。
C++は多重定義が可能な言語であり、利用者定義演算子は多重定義の枠組みに入っている。このためSmalltalkと異なり、引数が異なる場合に限って同じ名前空間で同じ名前の演算子を複数定義することが可能となっている。ただし、既存の演算子を上書きすることになってしまうため数値型だけを引数とする演算子の定義はできない。
いくつかのオブジェクト指向言語ではFORTRANと同じ可読性と記述性の観点で導入されているが、多くのオブジェクト指向言語においては数値型とオブジェクトを同一の関数(あるいはメソッド)で処理する観点で導入されておりそれらの言語では必須の機能となっている。
純粋なオブジェクト指向言語(特にSmalltalk)においてオブジェクトに対する操作は全てメソッドで受信可能なメッセージとして表されるべきであり、セレクターが記号になっているだけのメッセージである演算子は特別扱いすべきではない。このため優先度の違いはあるものの演算子は単なるセレクターの一種として位置づけられている。
Smalltalkによる例:
C++による例: