メソッド (method) あるいは メンバー関数 (-かんすう, member function) とはオブジェクト指向プログラミング言語において、あるクラスまたはオブジェクトに所属するサブルーチンを指す。

概要

編集

SmalltalkSimula (member procedure) C++ SimulaCJava[1]使C++Smalltalk[][?]OSSmalltalkJava

SmalltalkSmalltalkObjective-C使[2]

1 [3]

 ()  this  self  C++



 (UML)  (operation) 

インスタンスメソッドとクラスメソッド

編集

 (instance method) 使使

 (class method) 使C++Java (static method) 

インスタンスメソッドとクラスメソッドの例

編集

Smalltalkによる例

編集

Smalltalkによるインスタンスメソッドとクラスメソッドの例を示す。

Object
	subclass:		#MethodSample
	instanceVariableNames:	'name'		"インスタンスオブジェクトに持たせるインスタンス変数"
	classVariableNames:	''		"クラスオブジェクトとクラスオブジェクト直属のインスタンスオブジェクトの間で共有するクラス変数"
	poolDictionaries:	''		"クラスオブジェクトとインスタンスオブジェクトの間で共有するプール変数"
	category:		'Example'.
 

"インスタンスオブジェクトのインスタンス変数を操作するメソッド(インスタンスメソッド)"
MethodSample methodsFor: 'accessing'
!
givenName

	^ name.
!
givenName: aString

	name := aString.
!!

"インスタンスオブジェクトとクラスオブジェクトを操作するメソッド(インスタンスメソッド)"
MethodSample methodsFor: 'inter-accessing'
!
name

	^ self givenName, ' ', self class familyName. 
!!

MethodSample class instanceVariableNames: 'name'.	"クラスオブジェクトに持たせるインスタンス変数"

"クラスオブジェクトのインスタンス変数を操作するメソッド(クラスメソッド)"
MethodSample class methodsFor: 'accessing'
!
familyName
	^ name.
!
familyName: aString

	name := aString.
!!

MethodSample class methodsFor: 'instance creation'
!
withGivenName: aString

	^ self
		new
			givenName: aString;
			yourself.
!!

インスタンスメソッドを実行するには、まずインスタンスオブジェクトを生成しなければならない:

| objectA objectB |

objectA := MethodSample withGivenName: 'John'.
objectB := MethodSample withGivenName: 'Joe'.

上の例では #withGivenName: により二つのインスタンスオブジェクトを生成し変数 objectAobjectB に代入している。この時点で、objectAobjectB のインスタンス変数 name にはそれぞれ "John" と "Joe" が代入されている。

インスタンスメソッドを実行するには次のように記述する:

objectA givenName.	"'John' を返す"
objectB givenName.	"'Joe' を返す"

上の例では objectAobjectB それぞれのインスタンスオブジェクトに対し #givenName メッセージを送りインスタンスメソッドを実行している。それぞれのメソッドの返り値が異なることから、同じクラスオブジェクトに属するインスタンスオブジェクトでもインスタンス変数が持つ値は、インスタンスオブジェクト毎に異なることがわかる。

一方、クラスメソッドを実行するには、クラスオブジェクトに直接属しているため、インスタンスオブジェクトの代わりにクラスオブジェクトに対してメッセージを送る。 クラスメソッドを実行するには次のように記述する:

type := MethodSample
type familyName: 'Hillton'.
type familyName.		"'Hillton' を返す".

上の例では typeにクラスオブジェクトMethodSampleを代入して、#familyName#familyName:メッセージを送りクラスメソッドを実行している。

クラスオブジェクトのインスタンス変数 name は、インスタンスオブジェクトのインスタンス変数と異なり MethodSample に属する全てのインスタンスオブジェクトで共有される。 クラスオブジェクトのインスタンス変数が共有される例を示す:

| type objectA objectB |

type := MethodSample

objectA := type withGivenName: 'John'.
objectB := type withGivenName: 'Joe'.

"#nameはクラスオブジェクトに#familyNameを送っているため、異なるインスタンスオブジェクトでも'Hillton'が共有されている。"
type familyName: 'Hillton'.
objectA name.	"'John Hillton'を返す"
objectB name.	"'Joe Hillton'を返す"

クラスメソッドは、変数に代入せず直接クラス名を指定して呼び出すことが多い。特にクラスがオブジェクトではない言語においては、直接クラス名を指定する書き方しかできない。

直接クラス名を指定したクラスメソッドの呼び出しは次のように記述する:

MethodSample familyName: 'Hillton'.
MethodSample familyName.		"'Hillton' を返す".

MethodSample 使 new 

 new SmalltalkRubynewnewC++new () new



 (signature: ) SmalltalkObjective-C

Javaによる例

編集

Javaで記述したインスタンスメソッドと静的メソッド(クラスメソッド)の例を示す。Java では static 修飾子がついたメソッドが静的メソッドであり、ついていなければインスタンスメソッドである。

public class MethodSample {
  /** インスタンスフィールド */
  private String name;
  
  /** クラスフィールド */
  private static int number;
  
  /** インスタンスを生成するためのコンストラクタ */
  public MethodSample(final String name) {
    this.name = name;
  }
  
  /** インスタンスメソッド、getter */
  public String getName() {
    return this.name;
  }
  
  /** 静的メソッド、getter */
  public static int getNumber() {
    return MethodSample.number;
  }
  
  /** 静的メソッド、setter */
  public static void setNumber(final int number) {
    MethodSample.number = number;
  }
}

Smalltalk同様インスタンスメソッドを呼び出すには、まずコンストラクタを呼び出してインスタンスを生成しなければならない:

MethodSample objectA = new MethodSample("John");
MethodSample objectB = new MethodSample("Joe");

上記の例は、Smalltalkの例におけるインスタンスオブジェクトの生成と同様に動作する。C++の表記を踏襲したJavaでは、new演算子によってインスタンスを生成する。

インスタンスメソッドを呼び出すには次のように記述する:

objectA.getName(); // "John" を返す
objectB.getName(); // "Joe" を返す

上記の例は、Smalltalkの例におけるインスタンスメソッドの呼び出しと同様に動作する。

クラスメソッドを呼び出すには次のように記述する:

MethodSample.setNumber(100);
MethodSample.getNumber(); // 100 を返す

上記の例は、Rubyの例における直接クラス名を指定したクラスメソッドの呼び出しと同様に動作する。

Javaではメタクラスとしてjava.lang.Classクラスをサポートする。java.lang.Object.getClass()メソッドによりClass型オブジェクトを取得できる。また、クラス名.classという構文でClass型オブジェクトを取得することもできる。さらにリフレクションを使うことで、Class型オブジェクトからメソッドを呼び出したり、フィールドにアクセスしたりすることもできる。

.NET FrameworkではメタクラスとしてSystem.Typeクラスをサポートする。System.Object.GetType()メソッドによりType型オブジェクトを取得できる。C#ではtypeof演算子により型シンボルからType型オブジェクトを取得することもできる。また、リフレクションもサポートしている。

C++はクラス型オブジェクトやリフレクションをサポートせず、クラス自体を何らかの変数に代入するようなことはできない[4]

メッセージ送信とメソッド呼び出し

編集

オブジェクト指向を解説した書籍などでメソッド呼び出しについてオブジェクトにメッセージを送信すると表現されることがある。C++系統の言語ではオブジェクトの操作は単なるメンバー関数(メソッド)呼び出しに過ぎず比喩として捉えられる場合が多い。SmalltalkやObjective-Cにおいては、メッセージ送信は単なる比喩ではなく実体のある機構であり、メソッド呼び出しとは別物であるため注意が必要である。

仮想メソッド、抽象メソッドと具象メソッド

編集

仮想メソッド

編集

 (virtual method)  () C++

C++C#virtualC#Javafinalfinalfinal[5]

仮想と非仮想

編集

C++C++virtualC++templatetemplate[]delete便

C++C#[6][7]

Java[8]

JavafinalJavafinalJavafinal[9][10]OracleHotSpotVMfinal[5]

抽象メソッドと具象メソッド

編集

 (abstract method) C++ (pure virtual function) 

 (concrete method) 使

JavaC#abstractabstract使

Template Method 

JavaC# (interface) JavaC#

オーバーライド

編集

アクセサ

編集

 (accessor)  (set) setter (get) getter2settergetter1setter/getterC# 9init[11]

アクセサの表記

編集



JavagetXXX, setXXXSmalltalkXXX, XXX:Objective-CXXX, setXXX:setDelphiC#使RubyXXX=C++

アクセサとRADツール

編集

RADRAD (GUI) 

Javaget/setRADJavaBeans (java.beans) set/getBeansJavaset/get使set/getString.length()

アクセサと公開フィールド

編集

 (public)  使

11 (setter)  (getter) 0



 setter 

 () [12]

getter/setter 



setter  (validation) 



使

Smalltalk#value, #contents, #name, #size#value(1)#value(2)使

(1)
"アクセサ目的以外の#value"
[ 1 ] value. "-> 1"
( Continuation currentDo: [ :sink | sink value: 0. ] ) value. "-> 1"

"純粋なアクセサとしての#value"
( 1 ) asValueHolder value. "-> 1"
( 0 -> 1 ) value. "-> 1"

(2)

"共通の手順"
block :=
[ :valueHolder |
    self
        traceCr: valueHolder value printString.
].

"手順の適用"
block value: ( 1 ) asValueHolder.
block value: ( 0 -> 1 ).
block value: [ 1 ].
block value: ( Continuation currentDo: [ :sink | sink value: 0. ] ).

#value以外の実例

"アクセサ以外:1と10を元に計算している。"
( 1 to: 10 ) size.
"アクセサ"
#( 1 2 3 ) size.

"アクセサ以外:'text.txt'を全部読み込んだ結果を返す"
'text.txt' asFileRefarence readStream contents.
"アクセサ以外:self valueの結果を返す"
1 asValueHolder contents.
"アクセサ"
#( 1 2 3 ) contents.

"アクセサ以外: Class名を生成して返す。"
Class name.
"アクセサ"
CmCommand new name.


純粋なオブジェクト指向環境として知られるSmalltalkでは、アクセサによる多態性がMVCの依存性辞書[要説明]の管理を始めあらゆる箇所で活用されている。

アクセサ論争

編集

Smalltalk使 C++  public 

[13]





 IDE goto

C++CC++classstructCPOD (Plain Old Data) classstruct使

Object Pascal [14] Ruby 

多重定義

編集

 (overload) 

PHPPerl

参考文献・脚注

編集


(一)^ MFCCOM.NET Framework使

(二)^ SmalltalkObjective-CObjective-C class_getInstanceMethodMethod objc_msgSendmsg

(三)^ Smalltalk"#addSelector:withMethod:"[1]

(四)^ C++obj.staticMemberFunc()

(五)^ abJava | Java Magazine | Oracle

(六)^ Performance Tips and Tricks in .NET Applications | Microsoft Docs

(七)^ Writing Faster Managed Code: Know What Things Cost | Microsoft Docs

(八)^  | Android  | Android Developers, Internet Archive

(九)^ Java: ? final使 | IBM, Internet Archive

(十)^ Java:  | IBM, Internet Archive

(11)^  - C#   | Microsoft Docs

(12)^ C++/Java/C#publicconst/final/readonlygetter

(13)^ C/C++ (copy elision) Return Value Optimization (RVO)  - cppreference.com

(14)^ Properties (Delphi) - RAD Studio. docwiki.embarcadero.com. 20231013

関連項目

編集