これ(コンピュータープログラミング)

フリー百科事典ウィキペディアより
ナビゲーションにジャンプ 検索にジャンプ

thisself、およびMe、一部のコンピュータープログラミング言語で、現在実行中のコードが含まれるオブジェクト、クラス、またはその他のエンティティを参照するために使用されるキーワードです。したがって、これらのキーワードによって参照されるエンティティは、実行コンテキスト(どのオブジェクトがそのメソッドを呼び出しているかなど) に依存します。異なるプログラミング言語では、これらのキーワードの使用方法がわずかに異なります。「this」のようなキーワードが必須である言語では、現在のオブジェクトに格納されているデータとメソッドにアクセスする唯一の方法はキーワードです。オプションの場合、同じ名前の変数と関数のあいまいさを解消できます。

オブジェクト指向プログラミング

多くのオブジェクト指向 プログラミング言語では、 (またはthisとも呼ばれます) は、インスタンス メソッドで使用される変数であり、インスタンス メソッドが処理しているオブジェクトを参照します。最初の OO 言語であるSIMULA 67は、ローカル オブジェクトを明示的に参照するために使用されました。[1] : 4.3.2.3  C++およびそれから派生したスタイルの言語 ( JavaC#D、およびPHPなど) も一般に を使用しますObject PascalPerlPython_selfMethis thisRubyRustObjective-CDataFlexおよびSwiftを使用しますselfMicrosoft のVisual BasicではMe.

概念はすべての言語で似ています。通常は、現在のオブジェクトを参照thisする不変の参照またはポインターです。多くの場合、現在のオブジェクトは、キーワードを含むプロパティメソッド、サブルーチン、または関数の「親」として機能するコードです。thisオブジェクトが適切に構築またはインスタンス化された後thisは、常に有効な参照になります。一部の言語では明示的に必要です。他の人は、字句スコープを使用して暗黙的に使用し、クラス内のシンボルを可視化します。あるいは、 によって参照されている現在のオブジェクトthisは、キーワードを含む関数またはメソッドを呼び出した独立したコード オブジェクトである可能性があります。this. たとえば、Web ページの HTML タグに関連付けられたJavaScriptthisイベント ハンドラーが、ドキュメント オブジェクトの外側のグローバル スペースに格納されているキーワードを含む関数を呼び出すと、このようなことが起こります。そのコンテキストでthisは、囲んでいるウィンドウ オブジェクトではなく、ドキュメント オブジェクト内のページ要素を参照します。[2]

C++ や Java などの一部の言語では、thisorselfキーワードであり、変数はインスタンス メソッドに自動的に存在します。Python、Rust、Perl 5 などの他の言語では、インスタンス メソッドの最初のパラメーターがそのような参照です。明示的に指定する必要があります。Python と Perl では、パラメーターの名前は必ずしもthisorである必要はありませんself他のパラメータと同様に、プログラマが自由に名前を付けることができます。ただし、非公式の慣例により、Perl または Python のインスタンス メソッドの最初のパラメーターの名前はself. Rust では、呼び出された関数が invocant を借用するか、移動するかに応じて、 self オブジェクトを呼び出すか、または を呼び出す必要があります &selfself

C++ または Java の静的メソッドはインスタンスではなくクラスに関連付けられているためthis、オブジェクトがないため を使用できません。Ruby、Smalltalk、Objective-C、Swift などの他の言語では、メソッドはとして渡されるクラス オブジェクトに関連付けられ、クラス メソッドthisと呼ばれますクラス メソッドの場合、Python はを使用してクラス オブジェクトにアクセスしますcls

機微と難しさ

レキシカル スコープを使用して を推論する場合、コード内thisでの使用はthis、違法ではありませんが、メンテナンス プログラマーに警告を発する可能性がありthisます。同じ名前、またはメソッドが現在のオブジェクト、つまりthisそれ自体 への参照を返したい場合。

一部のコンパイラ ( GCCthisなど) では、明示的なポインター パラメーターを使用して、C++ インスタンス メソッドへのポインターを別の型のポインターに直接キャストできます。[3]

再帰を開く

のディスパッチ セマンティクスthis、つまり のメソッド呼び出しthisが動的にディスパッチされることは、オープン再帰と呼ばれ、これらのメソッドが派生クラスまたはオブジェクトによってオーバーライドされる可能性があることを意味します。対照的に、関数の直接の名前付き再帰または匿名再帰は、クローズド再帰を早期バインディングと共に使用します。たとえば、次の階乗のPerlコードでは、トークン__SUB__は現在の関数への参照です。

 機能 ":5.16"を使用します
サブ {
    私の $x  = シフト; 
    $x  ==  0  ?  1  :  $x  *  __SUB__ -> (  $x  -  1  ); 
}

対照的に、C++ では (this明確にするために明示的に使用しますが、必須ではありません)、thisオブジェクト自体にバインドしますが、クラス メソッドが「仮想」、つまりベースでポリモーフィックと宣言されている場合、動的ディスパッチ (遅延バインディング) によって解決されるため、派生クラスはそれをオーバーライドできます。

unsigned int factorial ( unsigned int n )    
{
  もし( n == 0 )   
    1を返します。 
  そうしないと
    return n * this -> factorial ( n - 1 );     
}

これは直接再帰であるため、この例は人為的であり、factorialメソッドをオーバーライドするとこの関数がオーバーライドされます。より自然な例は、派生クラスのメソッドが基本クラスの同じメソッドを呼び出す場合、または相互再帰の場合です。[4] [5]

脆弱な基本クラスの問題は、オープン再帰のせいであるとされており、デフォルトでメソッドを呼び出すにthisは、オープン再帰 (動的ディスパッチ、遅延バインディング) ではなく、クローズ再帰 (静的ディスパッチ、早期バインディング) を使用し、明確な場合にのみオープン再帰を使用することが提案されています。要求された; 外部呼び出し (を使用しないthis) は、通常どおり動的にディスパッチされます。[6] [7] JDK で実際にこれを解決する方法は、特定のプログラマーの規律によるものです。この規律は、C. Ruby と GT Leavens によって形式化されました。それは基本的に次のルールから成ります: [8]

  • publicのメソッドを呼び出すコードはありませんthis
  • 内部で (同じクラスの他のメソッドからの呼び出しによって) 再利用できるコードは、protectedorprivateメソッドにカプセル化されます。ユーザーにも直接公開する必要がある場合は、ラッパーpublicメソッドが内部メソッドを呼び出します。
  • 以前の推奨事項は、純粋なメソッドに対して緩和できます。

実装

C++

C++ の初期のバージョンでは、thisポインターを変更できました。そうすることで、プログラマーはメソッドがどのオブジェクトに取り組んでいるかを変更できました。この機能は最終的に削除され、現在thisC++ ではr-valueです。[9]

C++ の初期のバージョンには参照が含まれていませんでした。最初からC++thisに参照が含まれていた場合、ポインターではなく参照であったことが示唆されています。[10]

C++ では、オブジェクトはソース コード ステートメントで自身を破壊できます: delete this.

C#

C#のキーワードthis、参照型に対して Java と同じように機能します。ただし、C#値型内では、通常の変更可能な変数参照と同様に、まったく異なるセマンティクスを持ち、代入の左側で発生することさえあります。 this

C#での の使用法の 1 つthisは、同じ名前を持つローカル変数を含むメソッド内で外部フィールド変数への参照を許可することです。このような状況では、たとえば、var n = localAndFieldname;メソッド内のステートメントはローカル変数の型と値を に割り当てますlocalAndFieldnamen、ステートメントvar n = this.localAndFieldname;は外部フィールド変数の型と値を に割り当てますn[11]

D

クラスのD ではthis、構造体または共用体メソッドは、囲んでいる集合体のインスタンスの不変参照を参照します。クラスは参照型で、構造体と共用体は値型です。D の最初のバージョンでは、キーワード thisは、メソッドがバインドされているオブジェクトのインスタンスへのポインターとして使用されますが、D2 では、暗黙的refな関数引数の文字が含まれています。

ディラン

マルチメソッドをサポートし、 の概念を持たないオブジェクト指向言語であるプログラミング言語Dylanでは、オブジェクトにメッセージを送信することは依然として構文に保持されています。以下の 2 つの形式は同じように機能します。違いは単なるシンタックス シュガーです。 this

object.method(param1, param2)

メソッド (オブジェクト、param1、param2)

エッフェル

クラス テキスト内では、現在の型は現在のクラスから取得した型です。クラスの機能 (ルーチン、コマンド、クエリ) 内で、キーワードCurrentを使用して現在のクラスとその機能を参照できます。現在のクラス機能の名前を公然と参照するだけでキーワードが暗示されるため、キーワードの使用Currentはオプションです。Current例: クラス MY_CLASS に機能「foo」があり、次のように参照する場合があります。

  クラス
     私のクラス
  
  機能 -- アクセス
  
     foo : 整数
  
     my_function : 整数
        行う
          結果 := フー
       終わり
 
 終わり

[12]

Current10 行目 (上記) には、単純な「foo」の呼び出しによる 暗黙の参照があります。

10 行目 (以下) には、Current「Current.foo」への呼び出しによる明示的な参照があります。

  クラス
     私のクラス
  
  機能 -- アクセス
  
     foo : 整数
  
     my_function : 整数
        行う
           結果 := 現在ふー
       終わり
 
 終わり

どちらのアプローチもコンパイラーに受け入れられますが、暗黙のバージョン (例: x := foo) の方が冗長ではないため優先されます。

他の言語と同様に、次のCurrentようなキーワードの使用が義務付けられ ている場合があります。

  クラス
     私のクラス
  
  機能 -- アクセス
  
     my_command
           -- 「Current」で MY_OTHER_CLASS を作成します
        ローカル
           x :  MY_OTHER_CLASS
       行う
           xを作成しますmake_with_something  (現在)
       終わり
 
 終わり

上記のコードの場合、11 行目のmake_with_somethingへの呼び出しは、キーワード を明示的に渡すことによって現在のクラスを渡していCurrentます。

ジャバ

キーワードthisは、それが現れるクラスの現在のインスタンスを表すJava言語キーワードです。クラス変数とメソッドにアクセスするために使用されます。

Java ではすべてのインスタンス メソッドが仮想であるため、 thisnull になることはありません。[13]

JavaScript

JavaScript は、Web ブラウザーで広く使用されているプログラミング言語またはスクリプト言語thisであり、重要なキーワードですが、それが何に評価されるかは、使用される場所によって異なります。

  • グローバル空間で任意の関数の外で使用される場合this、囲んでいるオブジェクトを参照します。この場合は、囲んでいるブラウザ ウィンドウ (windowオブジェクト) です。
  • グローバル空間で定義された関数で使用される場合、キーワードが何thisを参照するかは、関数の呼び出し方法によって異なります。そのような関数が直接呼び出されると (例: f(x))、thisは関数が定義されているグローバル空間を参照し、他のグローバル関数と変数も存在する可能性があります (厳密モードでは ですundefined)。ただし、を含むグローバル関数がthisドキュメント オブジェクト内の要素のイベント ハンドラの一部として呼び出される場合this、呼び出し元の HTML 要素を参照します。
  • メソッドがnewキーワード (例: var c = new Thing()) を使用して呼び出されると、Thing 内で thisThing オブジェクト自体が参照されます。
  • 関数がオブジェクトのプロパティとしてアタッチされ、そのオブジェクトのメソッドとして呼び出される場合 (例: obj.f(x)) はthis、関数が含まれているオブジェクトを参照します。[14] [15]関数オブジェクトのまたはメソッドをthis使用して、関数を呼び出すときに手動で指定することもできます。[16]たとえば、メソッド呼び出しは次のように書くこともできます.call().apply()obj.f(x)obj.f.call(obj, x)

thisDOM イベント ハンドラーなどのネストされた関数での の異なる意味を回避するにthisは、呼び出し元オブジェクトの参照を変数 (一般にthatorと呼ばれるself) に保存し、その変数を使用して呼び出し元を参照するのが JavaScript の一般的なイディオムです。ネストされた関数内のオブジェクト。

例えば:

// この例では、$ は jQuery ライブラリ
$ ( ".element" ) への参照です。hover ( function ()  { 
    // ここでは、this と that の両方がマウス カーソルの下の要素を指しています。
    var  that  =  this ;
    
    $ (これ)。検索( 「.elements」)。each ( function ()  { 
        // ここでは、 this は繰り返される DOM 要素を指しています。
        // ただし、それは依然としてマウス カーソルの下の要素を指しています。
        $ ( this ). addClass ( "highlight" ); 
    }); 
});

特に、JavaScript は両方thisと関連するキーワードself[17]を使用し (どちらか一方を使用する傾向がある他のほとんどの言語とは対照的に)、self特に Web ワーカーに限定されています。[18]

最後に、グローバル (ウィンドウまたは同等の) オブジェクトを具体的に参照する信頼できる方法として、JavaScript はglobalThisキーワードを特徴としています。[19]

ルア

Lua では、演算子を使用して関数を定義するときに、シンタックス シュガーselfとして作成されます。[20]を使用してメソッドを呼び出す場合、インデックスが作成されるオブジェクトは、呼び出される関数の最初の引数として暗黙的に指定されます。 ::

たとえば、次の 2 つの関数は同等です。

ローカル オブジェクト =  {}

関数 obj . foo ( arg1 ,  arg2 ) 
  print ( arg1 ,  arg2 )  -- ここでは「self」を使用できません
end

function  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

PowerShell では、特別な自動変数 $_にパイプライン オブジェクトの現在のオブジェクトが含まれます。この変数は、パイプライン内のすべてのオブジェクトまたは選択されたオブジェクトに対してアクションを実行するコマンドで使用できます。[21]

"1" ,  "2" ,  "3"  |  %  { 書き込み$_  }

また、クラスやその他のユーザー定義型を定義するための正式な構文を追加する PowerShell 5.0 以降では、[22] $this変数はオブジェクトの現在のインスタンスを記述します。

パイソン

Python では、 のキーワードはありませんthisオブジェクトでメンバー関数が呼び出されると、オブジェクトのクラス オブジェクトで同じ名前のメンバー関数が呼び出され、オブジェクトは関数の最初の引数に自動的にバインドされます。したがって、インスタンス メソッドの必須の最初のパラメーターは次のように機能しthisます。このパラメータは慣習的に という名前ですが、任意のself名前を付けることができます。

クラス メソッド (classmethodデコレータで作成) では、最初の引数はクラス オブジェクト自体を参照し、慣習的に と呼ばれclsます。これらは主に継承可能なコンストラクターに使用されます[23]。クラスをパラメーターとして使用すると、コンストラクターのサブクラス化が可能になります。静的メソッド (staticmethodデコレータで作成) には、特別な最初の引数は存在しません。

さび

Rust では、型は関連する関数とは別に宣言されます。より伝統的なオブジェクト指向言語のインスタンス メソッドに類似するように設計された関数はself、最初のパラメーターとして明示的に取る必要があります。これらの関数は、instance.method()構文シュガーを使用して呼び出すことができます。例えば:

構造体 Foo { 
    バー: i32 
}

impl Foo {  
    fn  new ()  -> Foo { 
        Foo {バー: 0 , }   
    }
    fn 参照( &自己) { 
        プリントイン!( "{}" ,セルフ.バー); 
    }
    fn  mutate ( & mut self , baz : i32 ) {   
        セルフバー=バズ;  
    }
    fn 消費(自己) { 
        セルフ()を参照してください。
    }
}

これは、Foo関連する 4 つの関数を持つ型 を定義します。最初のFoo::new()はインスタンス関数ではないため、型の接頭辞を付けて指定する必要があります。残りの 3 つはすべてself、さまざまな方法でパラメーターを受け取り、ドット表記構文の砂糖を使用してインスタンスで呼び出すことができます。これは、明示的な最初のパラメーター Fooで型修飾された関数名を呼び出すことと同じです。self

let mut foo = Foo :: new (); // 型指定された関数fooとして呼び出す必要があります()を参照してください。// "0" を出力します。Foo::refer() には、 foo インスタンスfooへの読み取り専用アクセスがあります突然変異( 5 ); // &mut 仕様で許可されている場所で foo を変更します。 foo を mut fooと宣言する必要があります。() を消費します。// Foo::consume() は自分自身の完全な所有権を取得するため、"5" を出力して foo を破棄します     
 
 
 

// foo.refer() と同等
Foo :: refer ( foo ); // コンパイル エラー: foo は範囲外です 

自己

セルフ言語は、この「セルフ」の使用にちなんで名付けられました。

Xbase++

Selfクラスのメソッド内で厳密に使用されます。別の参照方法Selfは、 を使用すること::です。

も参照

参考文献

  1. ^ Dahl, Ole-Johan ; ミルハウグ、ビョルン。ナイガード、クリステン(1970)。"Common Base Language, Norwegian Computing Center" .
  2. ^ Powell, Thomas A, and Schneider, Fritz, 2012. JavaScript: The Complete Reference, Third Edition. マグロウヒル。第 11 章、イベント処理、p 428。ISBN 978-0-07-174120-0 
  3. ^ GNU Compiler Collection (GCC) の使用 –バインドされたメンバー関数
  4. ^ 閉じた再帰と開いた再帰」、 Ralf Hinze、2007 年 7 月
  5. ^ Open Recursion究極のラムダ
  6. ^ 選択的オープン再帰: 壊れやすい基底クラスの問題の解決策」、Jonathan Aldrich
  7. ^ " Selective Open Recursion: A Solution to the Fragile Base Class Problem ", Lambda the Ultimate
  8. ^ アルドリッチ、ジョナサン、ケビン・ドネリー. 選択的オープン再帰: コンポーネントと継承に関するモジュラー推論」 SAVCBS 2004 コンポーネントベース システムの仕様と検証 (2004): 26. JDK 採用ソリューション C. Ruby と GT Leavens の引用。「スーパークラス コードを見ずに正しいサブクラスを安全に作成する」. In Object-Oriented Programming Systems, Languages, and Applications, October 2000. doi : 10.1145/353171.353186テクニカル レポート TR #00-05dとしても入手可能
  9. ^ ISO/IEC 14882:2003(E): プログラミング言語 - C++ . ISO/IEC。2003年。
  10. ^ Stroustrup: C++ スタイルとテクニック FAQ
  11. ^ De Smet, Bart, 2011. C# 4.0 Unleashed. サムス・パブリッシング、インディアナポリス、アメリカ。Chapter 4, Language Essentials , p 210. ISBN 978-0-672-33079-7 
  12. ^ 注: 行番号は参考用です。Eiffel のクラス テキストには行番号がありません。ただし、Eiffel Studio IDE には行番号オプションがあり、参照用にオプションでオンにすることができます (ペア プログラミングなど)。
  13. ^ Barnes, D. and Kölling, M. Objects First with Java . 「...この構造を使用する理由 [this] は、名前のオーバーロードと呼ばれる状況があるためです。同じ名前が 2 つの異なるエンティティに使用されています...フィールドとパラメーターが類似した名前を共有していても、互いに独立して存在する変数を分離します。名前を共有するパラメーターとフィールドは、Java では実際には問題になりません。」[要出典]
  14. ^ Crockford, Douglas, 2008. JavaScript: The Good Parts . O'Reilly Media Inc. と Yahoo! Inc. Chapter 4, Functions , p 28. ISBN 978-0-596-51774-8 
  15. ^ Powell, Thomas A, and Schneider, Fritz, 2012. JavaScript: The Complete Reference, Third Edition. マグロウヒル。第 5 章、関数、pp 170–1。ISBN 978-0-07-174120-0 
  16. ^ Goodman, Danny, with Morrison, Michael, 2004. JavaScript Bible, 5th Edition. Wiley Publishing、Inc.、インディアナポリス、米国。Chapter 33, Functions and Custom Objects , p 987. ISBN 0-7645-5743-2 
  17. ^ Mozilla 開発者ネットワーク: Window.self
  18. ^ Mozilla Developer Network : Web Worker API
  19. ^ Mozilla 開発者ネットワーク: globalThis
  20. ^ "Lua でのプログラミング: 16" .
  21. ^ msdn. 「PowerShell: 自動変数について」 . docs.microsoft.com 2018 年3 月 22 日閲覧
  22. ^ msdn. "about_Classes" . docs.microsoft.com 2018 年12 月 17 日閲覧
  23. ^ Python 2.2 での型とクラスの統合、 Guido van Rossum、「 __new__ メソッドのオーバーライド

さらに読む