self
Objective-C での意味は? いつ、どこで使用すればよいですか?this
Javaと似ていますか?
6 に答える
self
作業している現在のクラスのインスタンスを指します。はい、this
Java に似ています。
そのクラスの現在のインスタンスに対して操作を実行する場合に使用します。たとえば、クラスでインスタンス メソッドを作成していて、同じインスタンスでメソッドを呼び出して何かを実行したり、データを取得したりしたい場合は、次のようにしますself
。
int value = [self returnSomeInteger];
これは、インスタンス変数の値を設定するだけでなく追加の機能を実装する場合、特にセッター メソッドを使用するインスタンスのアクセサー メソッド (つまり、セッターとゲッター) にもよく使用されます。その変数の値を設定したいときは、次のようにします。
[self setSomeVariable:newValue];
の最も一般的な用途の 1 つはself
、クラスの初期化中です。サンプル コードは次のようになります。
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
これにより、スーパークラスの ( 経由のsuper
) 初期化子が呼び出されます。これは、クラス階層を上って連鎖した初期化がどのように発生するかです。ただし、返される値は に設定されますself
。これは、スーパークラスの初期化子がスーパークラスとは異なるオブジェクトを返す可能性があるためです。
self
インスタンス メソッド内の現在のオブジェクトへのポインターと、クラス メソッド内の現在のクラスへのポインターを含む、すべての Obj-C メソッドに対する暗黙の引数です。
もう 1 つの暗黙の引数は_cmd
、メソッドに送信されたセレクターです。
Obj-C メソッドでself
のみ取得できることに注意してください。_cmd
たとえば、一部の C ライブラリからのコールバックとして C(++) メソッドを宣言すると、self または cmd を取得できません。
詳細については、Objective-C ランタイム プログラミング ガイドの「隠し引数の使用」セクションを参照してください。
はい、Java の「this」とまったく同じです。「現在の」オブジェクトを指します。
2 つの重要な注意事項:
クラス自体、たとえば
UIView
(私はUIView
オブジェクトについて話しているわけではありません) それ自体がオブジェクトであり、self
それに関連付けられた があります。たとえば、次self
のようにクラス メソッドで参照できます。// This works +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Class method! +(void) makeTheMostOfYourself { }
self
参照しようとしているのがクラスではなくオブジェクトであっても、コンパイラは警告やエラーを発生させないことに注意してください。この方法でクラッシュを引き起こすのは非常に簡単です。例えば:// This will crash! +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Object method! -(void) makeTheMostOfYourself { } // This will crash too! -(void) showYourself2 { [self performSelector: @selector(makeTheMostOfYourself2)]; } // Class method! +(void) makeTheMostOfYourself2 { }
悲しいことに、これによりクラス メソッドが少し使いづらくなります。これは、情報を隠蔽してカプセル化するための貴重なツールであるため残念です。ただ気をつけてください。
うわー、半分正解と誤解を招くヒントがたくさん。これにより、何年にもわたって受け入れられている回答があっても、Qに回答できます。
まず第一に、Java のようなアーリー バインディングの静的型付け言語と、Objective-C のようなレイト バインディングの動的型付け言語のコンテキストでのメッセージング/呼び出しの概念を比較するのは非常に困難です。ある時点でこれは壊れます。私はこう言います:いいえ、これは似ていません。なぜなら、両方の言語のタイピングとディスパッチの概念は根本的に異なるため、他の言語と似ているものは何もないからです。しかし、…</p>
次に、 の「両面」を区別する必要がありますself
。
A. 自分自身を使う
メッセージで使用する場合は、他のものと同様に単純なオブジェクト参照です。
[self doSomething];
[anotherObject doSomething];
技術的には、両方の回線が同じように機能します (もちろん、別の受信機を使用することを受け入れます)。これは特に、最初の行がのクラス内のメソッドの実行につながらないself
ことを意味します。なぜなら、self
は必ずしも「そのクラス」を参照しているわけではないからです。Objective-C 内のすべてのメッセージ (1 つの例外: へのメッセージsuper
) と同様に、サブクラスのメソッドの実行につながる可能性があります。
@interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
@end
@implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( @"A" );
}
@interface B : A
- (void)doSomething; // Not necessary, simply as a marker
@end
@implementation B
- (void)doAnotherThing
{
NSLog( @"B" );
}
このようなコードで
B *b = [B new;]
[b doSomething];
この線
[self doAnotherThing];
へのメッセージは他のすべてのメッセージと同様にレイト バインドされるため、 in classは( )A
の実行につながります。コンソールの結果は、「A」ではなく「B」になります。レシーバーとして使用する場合は、単一の特別なルールを考えてはいけません。まったくありません。-doAnotherThing
B
self
self
self
(そして、上記の例は、クラスメソッドで同じ状況が発生する可能性があるため、クラスメソッドで使用するための非常に良い例です。クラス自体を使用すると、ポリモーフィズムが壊れます。これは、OOP で最悪のアイデアの 1 つです。クラスメソッドで使用してくださいself
) 、 それも。)
B.取得self
self
指しているのは何ですか?現在のメソッドの実行の原因となったメッセージの送信先オブジェクトを指します。
…</p>
…[someObject doSomething]… // some object is a reference to an instance object
…メッセージとして、メソッドが呼び出されます。最も単純なケースでは…</p>
- (void)doSomething
{ … }
このような場合、メソッドが属するクラスのインスタンスを指すself
ことができます。また、メソッドが属するサブクラスのインスタンスを指すこともできます。あなたは知りません。(そして、この情報は、上記で説明したように、メッセージを送信するために使用して保存されます。)self
メッセージがクラス オブジェクトに送信される場合、メッセージself
の受信者であるクラス オブジェクトを指します。これは完全に類似しています。したがって、 がself
サブクラス オブジェクトを指している可能性があります。
@interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
@end
@implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( @"A" );
}
@interface B : A
- (void)doSomething; // Not necessary, simply as a marker
@end
@implementation B
+ (void)doAnotherThing
{
NSLog( @"B" );
}
このクラスを持つ
…[A doSomething]…
self
inside -doSomething
( A
) は のクラス オブジェクトを指しますB
。したがって [self doAnotherThing]
、B
(!) が実行されます。これは明らかに違う
+ (void)doSomething
{
[A doAntoherThing];
}
後者のバージョンは、OOP の原則に関連する害を引き起こします。
補足としてself
、ルート クラスのクラス メソッド内で、ルート クラスまたは任意のサブクラスのインスタンス オブジェクトを指すことが可能です。でカテゴリを作成するときは、このことを念頭に置いておく必要がありますNSObject
。
self は、現在のインスタンス ディスパッチ テーブルへのオブジェクト ポインタです。これは、オブジェクトのすべてのメンバー関数に対する暗黙的な最初の引数であり、その関数が呼び出されたときに割り当てられます。
init のような関数では、スーパー クラス init を呼び出すときに、スーパー クラス init が self が指すものを再定義する可能性があるため、self を戻り値として再割り当てすることに注意する必要があります。
super は、スーパークラスのディスパッチ テーブルを指していることを除いて、self に似ています。