アクセサとは?

メソッド (method) あるいは メンバ関数 (-かんすう, member function) とはオブジェクト指向プログラミング言語において、あるクラスないしオブジェクトに所属するサブルーチンを指す。
C++ などの一部のプログラミング言語では、メソッドはメンバ関数と呼称される。「メンバ」関数という限定的な呼び名からも明らかなように、メンバでない関数の存在を言外に示しており、そのため Java などそのような関数が存在しない (全てのサブルーチンが何らかのクラスに所属する) 言語ではメソッドという用語を用いることが多い。また Objective-C のように関数が存在する言語でも、機能を直接指定する関数と動的ディスパッチを行うメソッドの差異から「メンバ関数」という用語が適当でない場合がある。しかしいずれにせよメソッドとメンバ関数の間に概念上明確な差はない。
メソッドと通常の関数の違いは主にインスタンス内部へのアクセスの有無である。この機能は通常カプセル化と呼ばれており、クラス定義の抽象化に貢献するとされる。また呼び出し時に操作の対象となるインスタンス(レシーバ) を self や this といった予約語、あるいはメソッドに渡された引数によって参照することができる。 C++ ではクラスに属さない関数であるグローバル関数と対比されることがある。
またメンバ関数はサブクラス化の際にオーバーライドされる可能性があり (多態性)、実際に発生する動作がレシーバに依存するという特徴を持つ。
インスタンスメソッド (instance method) とはインスタンスに属するメソッドのことであり、生成されたインスタンスからアクセスする。インスタンスメソッドはオブジェクト指向プログラミングの中核をなし、もっともよく使われれる。
一方、静的メソッド (static method) あるいは クラスメソッド (class method) とはクラスに属するメソッドのことであり、インスタンスを生成せずにクラスから直接呼び出すことができる。基本的に、その振る舞いは非オブジェクト指向言語における関数と変わらない。
インスタンスメソッドと静的メソッドの例を以下の Java によるサンプルで示す。Java では static 修飾子がついたメソッドが静的メソッドであり、ついていなければインスタンスメソッドである。
インスタンスメソッドを呼び出すには、まずコンストラクタを呼び出してインスタンスを生成しなければならない:
上の例では obj1 と obj2 の二つのインスタンスを生成した。この時点で、obj1 とobj2 のインスタンスフィールド name にはそれぞれ "John" と "Joe" が代入されている。
上の例では obj1 と obj2 それぞれのインスタンスに対し getName メソッドを呼び出した。それぞれの呼び出しの返り値が異なることから、インスタンスフィールドは、そのクラスに属する各オブジェクト毎に異なる値を持つことがわかる。
一方、静的メソッドはクラスに直接属しているため、呼び出す際はコンストラクタによってインスタンスを生成せずとも、即座にメソッドを呼び出せる。静的メソッドを呼び出すには次のように記述する:
このとき、 MethodSample が複数のインスタンスを生成しても、静的フィールド number はすべての MethodSample クラスに属するインスタンスの間で共有される。
仮想メソッド (virtual method) (C++では仮想関数)とは、サブクラスでオーバーライドし、動作を変更することのできるメソッドのことである。
C++およびC#ではメソッドにvirtual修飾子をつけることで仮想メソッドとすることができる。一方Javaではメソッドはデフォルトで仮想メソッドとなり、final修飾子をつけることで非仮想メソッドとなる。
一般に、仮想メソッドはコンパイル時にどのメソッドを呼び出すかを確定できないため、通常のメソッド呼び出しよりもパフォーマンスが悪いというデメリットがある。そのため、パフォーマンスを気にする多くのC++プログラマは、とくに継承する必要がないときはメンバ関数にvirtual修飾子をつけることを非常に嫌がる。
その影響もあってか、Javaでも、「Javaはデフォルトで仮想的だからfinalをつけないとパフォーマンスが衰える。」と言われるようになった。しかし、Javaコンパイラの最適化技術は大幅に進歩し、finalをつければパフォーマンスが向上するということは無くなってしまった。そのため、今日ではfinalをつければ高速化するという話は都市伝説であると言われるようになった[1]。
抽象メソッド (abstract method) 、あるいはC++では純粋仮想関数 (pure virtual function) とは仮想メソッドの一種で、メソッドの実装が無く、宣言だけされているもののことである。このメソッドを利用するには、このメソッドを含むクラスを継承し、そこでこのメソッドをオーバーライドして実装する必要がある。従って、抽象メソッドを含むクラスは継承しない限りインスタンス化できない。このようなクラスを抽象クラスと呼ぶ。
具象メソッド (concrete method) は抽象メソッドの逆で、実装をもつメソッドのことである。主に抽象メソッドをオーバーライドしたインスタンスメソッドのことを意味するために使われる。
Javaではabstract修飾子を用いて抽象メソッドを宣言できる。抽象メソッドを持つクラスもまた、必ずabstract修飾子を使わなければならない。
抽象メソッドはデザインパターンの一つTemplate Method パターンで主要な役割を果たす概念であり、ソフトウェアの拡張性、再利用性、汎用性を高めるのに役立つ。
C#では、オーバーライドしたメソッドにはoverride修飾子をつけることで、そのメソッドがオーバーライドされていることをコンパイラに知らせることができる。 同様に、Javaでも、Java SE 5から導入されたアノテーション@Overrideを用いることでメソッドがオーバーライドされていることをコンパイラに知らせることができる。
あるスーパークラスとそれを継承したサブクラスが別々の開発者によって実装されている場合、Javaではオーバーライドに関係した問題が起こりうるので注意が必要である。スーパークラスの実装者があとからメソッドを追加したときに、そのメソッドと同じ名前とシグネチャのメソッドが既にサブクラスに存在すると、オーバーライドしたつもりがないのに関係のないメソッドをオーバーライドしてしまうという問題が起こる。これを回避するためにJavaでは@Overrideの指定が推奨されるが、後方互換性を保つために必須とはなっていない。C#ではoverride修飾子が必須なのでこの問題は起こらない。
アクセサ (accessor) とは、メソッドの中で特にオブジェクトの属性やプロパティを取得するメソッド (getter) と設定するメソッド (setter) の対のこと。基本的に getXXX, setXXX のように語幹部が揃っているものをいう。
フィールドへの直接アクセスと比較した際のアクセサの利点は、第一に、意図的に setter メソッドを実装しないことで、フィールドの値を勝手に変更させないようにイミュータブル(不変)なクラスを作ることが可能になることが挙げられる。第二に、getter/setter でフィールドへアクセスするときにデータを加工してから取得したり挿入することができるという点である。第三に、setter でフィールドにデータをセットするときにセットしたいデータを例えば整数のみ、あるいは自然数のみ、偶数のみ、日付のみ、などに限定することができるという点である。第四に、モジュール間の依存関係を疎にしやすくなり、オブジェクト指向言語としての利点を活かせるという利点がある。
Smalltalk や Objective-Cのようなメッセージ送信メタファーの言語では、インスタンス変数は必ずアクセサを用いて利用するというのが常識である。一方 C++ などでは public 変数への直接フィールドアクセスが往々にして利用されることがある。
効率の問題。メソッドをいちいち呼び出すコストを避けたい場合。ただしほとんどはインライン化で解決できる。
記述量の問題。単純に値をセット、取得するだけのことに全てメソッドを記述するのは間違っているという考え方。
まず多態性の観点から、アクセサを用いない変数参照は将来にわたっての変更耐久性が著しく劣る。また記法の一貫性からアクセサを指示する向きもある。一方否定派は「強力な IDE を用いればリファクタリングは可能であり、むしろフィールドへの直接アクセスを用いる方が意味が明確となる」という主張を展開し、時にフレームに発展する場合がある。これは現代の「goto文論争」ともいうべき、半ば宗教的な対立関係である。
C# はこの反省から、アクセサ定義を簡素化する要素としてプロパティを導入した。また Ruby など、アクセサを簡単に定義できるメソッドや構文を備えている言語もある。
Java には、Java Beans と呼ばれる技術が存在する。これはアクセサと同じ役割を果たすクラスを作るためにある。Bean であるクラスがアクセサを持つクラスである。あるクラスを Bean にしたいアクセサメソッド名を set や get で始まる名前にするという命名規約に基づき命名することでそのクラスを一応、Bean にすることができる。
厳密には、Java Beans を作るには、Serializable インタフェースを実装し、マニフェストファイルに所定の情報を記述する必要があるが、ここではそれは重要なことではないので省略する (Java Beans を参照せよ)。
C# ではそのような命名規約を使わずともプロパティという技術を用いることで簡素化できる。そのため、Java はプロパティの扱いだけ C# よりも不便だという声もある。
しかし、この問題は Java SE 5 から導入されたアノテーションを用いることで容易に解決することもできる。
多くのオブジェクト指向言語ではメソッドやコンストラクタをオーバーロード (overload) できる機能を持つ。これは、オーバーライドと名前が似ているため間違えられることがある。引数の数、型、順序などが異なる同じ名前のメソッドを定義することをメソッドのオーバーロードという。
ただし、PHPやPerlのように、プログラミング言語によっては、型の曖昧さが原因によりメソッドをオーバーロードできないものもある。この場合はメソッドの引数をメソッド先頭で読み取り、引数の型を判定する条件分岐で対応する。
^ Javaの理論と実践: パフォーマンスの都市伝説 ガーベッジ・コレクターなどのプログラミングに棲みついているワニについて 都市伝説その2: クラスやメソッドをfinalとして宣言すると処理が速くなる

[ 186] メソッド (計算機科学) - Wikipedia
[引用サイト]  http://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5



お気に入り



  • track feed
    • seo