this、 self、 Me は、一部のプログラミング言語で使用されるキーワードで、現在実行中のコードが属するオブジェクト、クラス、またはその他のエンティティを参照するために使用されます。参照されるエンティティは、実行コンテキスト(メソッドが呼び出されるオブジェクトなど)によって異なります。プログラミング言語によって、これらのキーワードの使い方は若干異なります。などのキーワードが必須の言語では、キーワードは現在のオブジェクトに格納されているデータやメソッドにアクセスする唯一の方法です。オプションの場合、これらのキーワードは同じ名前の変数や関数を区別するために使用できます。this
多くのオブジェクト指向プログラミング言語では、this(またはとも呼ばれるself)は、インスタンス メソッドで操作対象のオブジェクトを参照するためにMe使用される変数です。最初のオブジェクト指向言語であるSIMULA 67は、ローカル オブジェクトを明示的に参照するために を使用しました。[ 1 ] : 4.3.2.3 C++およびスタイルが C++ から派生した言語(Java、C#、D、PHPなど)も一般的に を使用します。SmalltalkやObject Pascal、Perl、Python、Ruby、Rust、Objective-C、DataFlex、Swiftなどの言語はを使用します。Microsoft のVisual Basic はを使用します。thisthisselfMe
この概念はすべての言語で似ています。は通常、現在のオブジェクトを参照するthis不変の参照またはポインタです。現在のオブジェクトは多くの場合、キーワードを含むプロパティ、メソッド、サブルーチン、または関数の「親」または「呼び出し元」として機能するコードですthis。オブジェクトが適切に構築またはインスタンス化されると、thisは常に有効な参照になります。一部の言語では明示的に を要求しますが、他の言語では字句スコープを使用して暗黙的に を使用し、クラス内のシンボルを可視化します。あるいは、 が参照する現在のオブジェクトは、thisキーワードを含む関数またはメソッドを呼び出した独立したコード オブジェクトである可能性がありますthis。たとえば、Web ページの HTML タグに添付されたJavaScriptthisイベント ハンドラが、ドキュメント オブジェクトの外部のグローバル スペースに格納されているキーワードを含む関数を呼び出す場合、このようなことが起こります。この場合、thisは囲んでいるウィンドウ オブジェクトではなく、ドキュメント オブジェクト内のページ要素を参照します。[ 2 ]
thisC++、Java、Rakuなどの一部の言語では、またははキーワードselfであり、インスタンス メソッドに変数が自動的に存在します。Python、Rust、Perl 5 などの他の言語では、インスタンス メソッドの最初のパラメータは参照です。明示的に指定する必要があります。Python と Perl では、パラメータは必ずしもまたはという名前である必要はなく、他のパラメータと同様にプログラマが自由に名前を付けることができます。ただし、非公式な慣習として、Perl または Python のインスタンス メソッドの最初のパラメータはという名前です。Rust では、呼び出される関数が呼び出し元を借用するか、または移動するかに応じて、 self オブジェクトをまたはと呼ぶ必要があります。thisselfself&selfself
C++ や Java の静的メソッドはインスタンスではなくクラスに関連付けられているため、thisオブジェクトが存在しないため を使用できません。Ruby、Smalltalk、Objective-C、Swift などの他の言語では、メソッドはとして渡されるクラスオブジェクトthisに関連付けられており、クラスメソッドと呼ばれます。Python では、クラスメソッドの場合、 を使用してクラスオブジェクトclsにアクセスします。
字句スコープを使用して推論する場合this、コード内での使用はthis違法ではありませんが、保守プログラマーに警告を発する可能性があります。ただし、thisこの場合にも、同じ名前のローカル変数によって隠されたインスタンス変数を参照する場合や、メソッドが現在のオブジェクト、つまり自身への参照を返す場合など、正当な使用方法がありますthis。
一部のコンパイラ(例えばGCC)では、C++インスタンスメソッドへのポインタを、明示的なポインタパラメータを使用して、別の型のポインタに直接キャストできますthis。[ 3 ]
のディスパッチセマンティクスthis、つまり のメソッド呼び出しが動的にディスパッチされるという性質は、オープン再帰thisと呼ばれ、派生クラスやオブジェクトによってこれらのメソッドをオーバーライドできることを意味します。対照的に、関数の直接名前付き再帰または匿名再帰では、静的ディスパッチを伴うクローズド再帰が使用されます。たとえば、次の階乗のPerlコードでは、トークンは現在の関数への参照です。__SUB__
use feature ":5.16" ; sub { my $x = shift ; $x == 0 ? 1 : $x * __SUB__ -> ( $x - 1 ); }対照的に、C++ では (this明確化のために明示的に使用していますが、必須ではありません) this、オブジェクト自体にバインドされますが、クラス メソッドが基底クラスで宣言されている場合、つまりポリモーフィックである場合は、動的ディスパッチvirtualによって解決され、派生クラスがそれをオーバーライドできます。
class Number { private : unsigned int n ; public : // ...unsigned int factorial () { if ( n == 0 ) { return 1 ; } else { return n * this -> factorial ( n - 1 ); } } };この例は直接再帰であるため、人為的なものです。factorial()メソッドをオーバーライドすると、この関数もオーバーライドされます。より自然な例としては、派生クラスのメソッドが基底クラスの同じメソッドを呼び出す場合や、相互再帰の場合などがあります。[ 4 ] [ 5 ]
脆弱な基底クラスの問題はオープン再帰に起因するとされ、メソッドの呼び出しはthisデフォルトでオープン再帰(動的ディスパッチ)ではなくクローズド再帰(静的ディスパッチ)を使用し、オープン再帰は明示的に要求された場合にのみ使用するという提案がthisなされています。外部呼び出し(を使用しない)は通常どおり動的にディスパッチされます。[ 6 ] [ 7 ] JDK で実際にこの問題を解決する方法は、特定のプログラマ規律によるものです。この規律は C. Ruby と GT Leavens によって形式化されており、次のルールで構成されています。[ 8 ]
publicは のメソッドを呼び出しませんthis。protectedまたはprivateメソッドにカプセル化されます。ユーザーに直接公開する必要がある場合は、ラッパーpublicメソッドが内部メソッドを呼び出します。C++の初期バージョンではthisポインタを変更することができました。これにより、プログラマはメソッドが操作するオブジェクトを変更することができました。この機能は最終的に削除され、現在thisC++では右辺値となっています。[ 9 ]
C++の初期バージョンには参照が含まれていなかったため、もし最初からC++thisに参照が含まれていたら、ポインタではなく参照になっていただろうと示唆されている。 [ 10 ]
C++では、ソースコードのステートメントを使用してオブジェクトを自身で破棄できます。ただし、これはヒープに割り当てられたオブジェクトに対してのみ有効です。deletethis;
import std ;class SelfDestructing { private : int refCount = 0 ;~ SelfDestruct () { std :: println ( "Running destructor" ); } public : void addReference () { ++ refCount ; }void release () { --refCount ; if ( refCount <= 0 ) { delete this ; // インスタンスを削除return ; //すぐに戻る。インスタンスはもはや有効ではない} } };int main () { SelfDestructing * x = new SelfDestructing (); x -> addReference ();x -> release (); // "Running destructor" と出力します}C++23では、明示的なオブジェクト パラメータ (通称「推論」) は、メンバ関数内の暗黙的なパラメータにthis明示的に名前を付けることができる機能であり、テンプレートがオブジェクトの型、修飾子、および値のカテゴリを自動的に推論できるようにします。[ 11 ]this
import std ;std :: vectorを使用します。// これを推論せずに: // const/参照型の4つの異なる組み合わせclass Playlist { private : vector <Song> songs ; public : // ...Song & operator []( size_t i ) & { return songs [ i ]; }const Song & operator []( size_t i ) const & { return songs [ i ]; }Song && operator []( size_t i ) && { return std :: move ( songs [ i ]); }const Song && operator []( size_t i ) const && { return std :: move ( songs [ i ]); } };// これを推論すると、// オーバーロードは単一のメンバクラスに統合されます。 Playlist { private : vector < Song > songs ; public : // ...template < typename Self > decltype ( auto ) operator []( this Self && self , size_t i ) { return std :: forward < Self > ( self ). songs [ i ]; } };これは再帰ラムダ式を作成するためにも使用されています。
auto fib = []( this auto self , int n ) -> int { if ( n <= 1 ) { return n ; } return self ( n - 1 ) + self ( n - 2 ); }さらに、CRTP( Curiously Recurring Template Pattern )を使用する際に、宣言を簡略化するためにも使用できます。
C#thisのキーワードは、参照型に関しては Java と同様に機能します。しかし、C# の値型においては、セマンティクスがかなり異なり、通常の可変変数参照に似ており、代入式の左辺にも使用できます。this
C# におけるの用途の 1 つは、同じ名前のローカル変数thisを含むメソッド内で、外部フィールド変数を参照できるようにすることです。このような状況では、たとえば、メソッド内のステートメントはローカル変数の型と値を に割り当てますが、ステートメントは外部フィールド変数の型と値を に割り当てます。[ 12 ]stringn=localAndFieldname;localAndFieldnamenstringn=this.localAndFieldname;n
D 言語でthisは、クラス、構造体、または共用体のメソッドは、囲んでいる集合体のインスタンスへの不変参照を参照します。クラスは参照型であり、構造体と共用体は値型です。D言語の最初のバージョンでは、キーワードは メソッドがバインドされているオブジェクトのインスタンスへのポインタとして使用されていましたが、D2では暗黙の(参照渡しによるthis)関数引数としての性質を持ちます。ref
オブジェクト指向言語でマルチメソッドをサポートし、という概念を持たないプログラミング言語Dylanでは、オブジェクトへのメッセージ送信は依然として構文内に保持されています。以下の2つの形式は同じように機能します。違いは単なる構文糖衣です。this
object.method(param1, param2)
そして
メソッド(オブジェクト、パラメータ1、パラメータ2)
クラステキスト内では、現在の型は現在のクラスから取得した型です。クラスの機能(ルーチン、コマンド、クエリ)内では、キーワードを使用してCurrent現在のクラスとその機能を参照できます。キーワードの使用はCurrent任意です。現在のクラス機能の名前を明示的に参照するだけで、キーワードがCurrent暗黙的に使用されるためです。例:クラス MY_CLASS に機能 `foo` があり、次のように参照できます。
クラス私のクラス機能-- アクセスfoo :整数my_function :整数する結果:= foo終わり終わり上記の10行目には、Current単純な`foo`の呼び出しによって暗黙的に参照が含まれています。
10行目(下記)には、Current`Current.foo` の呼び出しによる明示的な参照があります。
クラス私のクラス機能-- アクセスfoo :整数my_function :整数する結果:=現在のfoo終わり終わりどちらの方法もコンパイラにとっては許容範囲内ですが、暗黙的に示される方法(例:)の方が冗長性が少ないため推奨されます。x := foo
他の言語と同様に、キーワードの使用Currentが義務付けられている場合もあります。例えば、次のような場合です。
クラス私のクラス機能-- アクセス私のコマンド-- `Current` を使用して MY_OTHER_CLASS を作成します。地元x : MY_OTHER_CLASSするcreate x . make_with_something ( Current )終わり終わり上記のコードの場合、11行目のmake_with_somethingの呼び出しでは、キーワードを明示的に渡すことで現在のクラスを渡していますCurrent。
キーワードは、 Javathis言語のキーワードであり、それが出現するクラスの現在のインスタンスを表します。クラスの変数やメソッドにアクセスするために使用されます。
Java ではすべてのインスタンス メソッドは仮想であるため、this決して になることはありませんnull。[ 14 ]
JavaScriptは、Webブラウザで広く使用されているプログラミング言語またはスクリプト言語thisですが、重要なキーワードです。ただし、その評価結果は使用される場所によって異なります。
this囲んでいるオブジェクト、この場合は囲んでいるブラウザウィンドウ、windowつまりオブジェクトを指します。this参照する対象は、関数の呼び出し方法によって異なります。このような関数が直接呼び出される場合(例f(x):)、thisは関数が定義されているグローバル空間を参照し、そこには他のグローバル関数や変数も存在する可能性があります(厳密モードでは、となりますundefined)。ただし、を含むグローバル関数がthisドキュメントオブジェクト内の要素のイベントハンドラの一部として呼び出される場合、thisは呼び出し元の HTML 要素を参照します。newキーワード (例: ) を使用して呼び出されると、 内では、オブジェクト自体が参照されます。letfoo=newFoo()FoothisFooobj.f(x):)、this関数が含まれているオブジェクトを参照します。[ 15 ] [ 16 ]関数オブジェクトのメソッドまたはメソッドthisを使用することで、関数を呼び出すときに手動で指定することも可能です。[ 17 ]例えば、メソッド呼び出しは、と記述することもできます。.call().apply()obj.f(x)obj.f.call(obj, x)thisDOM イベント ハンドラなどのネストされた関数におけるの異なる意味を回避するために、JavaScript ではthis呼び出し元のオブジェクトへの参照を変数 (一般的にthatまたは と呼ばれるself) に保存し、ネストされた関数内でその変数を使用して呼び出し元のオブジェクトを参照するという慣用法がよく用いられます。
例えば:
// この例では、$ は jQuery ライブラリへの参照です。 $ ( ".element" ). hover ( function () { // ここでは、this と that の両方がマウス カーソル下の要素を指しています。let that = this ; $ ( this ). find ( '.elements' ). each ( function () { // ここでは、this は反復処理中の DOM 要素を指しています。// ただし、that は依然としてマウス カーソル下の要素を指しています。$ ( this ). addClass ( "highlight" ); }); });this特にJavaScriptは、両方と関連キーワードself[ 18 ]を使用する(他のほとんどの言語はどちらか一方を使用する傾向があるのとは対照的)が、はselfWebワーカーに限定されている[ 19 ] 。
最後に、グローバルオブジェクト(ウィンドウまたはそれに相当するもの)を具体的に参照するための確実な方法として、JavaScriptにはglobalThisキーワードが用意されています。[ 20 ]
Luaでは、関数が演算子を使用して定義されると、構文糖衣selfとして作成されます。[ 21 ]を使用してメソッドを呼び出すと、インデックス付けされたオブジェクトが、呼び出される関数の最初の引数として暗黙的に渡されます。::
例えば、以下の2つの関数は同等です。
ローカルオブジェクト= {}function obj.foo ( arg1 , arg2 ) print ( arg1 , arg2 ) -- ここでは「self」を使用できませんendfunction obj : bar ( arg ) print ( self , arg ) -- "self" は arg の前の暗黙の最初の引数ですend-- すべての関数は「.」または「:」のどちらの方法でも呼び出すことができます。obj : foo ( "Foo" ) -- obj.foo(obj, "Foo") と同等obj . bar ( obj , "Bar" ) -- obj:bar("Bar") と同等Lua自体はオブジェクト指向ではありませんが、メタテーブルと呼ばれる別の機能と組み合わせることで、selfプログラマーはオブジェクト指向プログラミングに似た方法で関数を定義できるようになります。
PowerShell では、特別な自動変数$_にはパイプライン オブジェクト内の現在のオブジェクトが格納されます。この変数は、パイプライン内のすべてのオブジェクトまたは選択されたオブジェクトに対してアクションを実行するコマンドで使用できます。[ 22 ]
「1」、「2」、「3」| % { write $_ }また、クラスやその他のユーザー定義型を定義するための正式な構文を追加したPowerShell 5.0以降では、[ 23 ]$this変数はオブジェクトの現在のインスタンスを表します。
Python では、 のキーワードはありませんthis。オブジェクトに対してメンバ関数が呼び出されると、そのオブジェクトのクラスオブジェクトに対して同じ名前のメンバ関数が呼び出され、オブジェクトは自動的に関数の最初の引数にバインドされます。したがって、インスタンスメソッドの必須の最初のパラメータは として機能します。thisこのパラメータは慣例的に という名前ですselfが、任意の名前を付けることができます。
クラスメソッド(デコレータで作成@classmethod)では、最初の引数はクラスオブジェクト自体を参照し、慣習的に と呼ばれますcls。これらは主に継承可能なコンストラクタに使用され、[ 24 ]クラスをパラメータとして使用することでコンストラクタをサブクラス化できます。静的メソッド(@staticmethodデコレータで作成)には、特別な最初の引数はありません。
Rustでは、型はそれに関連付けられた関数とは別に宣言されます。より伝統的なオブジェクト指向言語のインスタンスメソッドに類似するように設計された関数は、self最初のパラメータとして明示的に受け取る必要があります。これらの関数は、構文糖衣を使用して呼び出すことができますinstance.method()。例:
struct Foo { bar : i32 , }impl Foo { fn new () -> Foo { Foo { bar : 0 , } }fn refer ( & self ) { println! ( "{} " , self.bar ) ; }fn mutate ( & mut self , baz : i32 ) { self . bar = baz ; }fn consume ( self ) { self.refer ( ) ; } }これは、4 つの関連関数を持つ型 を定義しますFoo。最初の関数Foo::new()はインスタンス関数ではないため、型プレフィックス を付けて指定する必要があります。残りの 3 つの関数はすべてself、さまざまな方法でパラメータを受け取り、Fooドット表記構文糖衣を使用してインスタンスに対して呼び出すことができます。これは、型修飾関数名を明示的なself最初のパラメータとともに呼び出すことと同じです。
let mut foo : Foo = Foo :: new (); // 型指定関数として呼び出す必要がありますfoo . refer (); // "0" と出力します。Foo::refer() は foo インスタンスへの読み取り専用アクセスを持ちますfoo . mutate ( 5 ); // foo をその場で変更します。&mut 仕様で許可されています。foo が宣言されている必要があります mut foo . consume (); // "5" と出力し、foo を破棄します。Foo::consume() は self の完全な所有権を取得します// foo.refer() と同等Foo :: refer ( foo ); // コンパイルエラー: foo はスコープ外です「自己」という言語は、この「自己」という言葉の使い方にちなんで名付けられました。
Selfは、クラスのメソッド内でのみ使用されます。 を参照する別の方法は、Selfを使用することです::。
{{cite web}}: CS1 maint: 複数の名前: 著者リスト (リンク)