3

自己が基本クラスのインスタンスを格納できる場合、自己を返すときに、どのように派生インスタンスに変換されるか。

4

3 に答える 3

4

これがあなたが求めていることだと思います: 基本クラス Base とサブクラス Derived があるとします。-[Derived init]別のインスタンスを呼び出し-[Base init]て返す場合-[Base init]、その別のインスタンスはのインスタンスでBaseあり、そうでないDerivedため不適切ではないでしょうか? たとえば、新しいオブジェクトにはDerived、クラスに追加された可能性のあるインスタンス変数がありません。

答えは、それBaseを行うことは許可されていません。元のインスタンスを置き換える場合は、その元のインスタンスの動的な型を尊重する方法で行う必要があります。たとえば、次のようなことができます。

// Re-allocate with 100 extra bytes
id newSelf = NSAllocateObject([self class], 100, [self zone]);
[self release];
self = newSelf;
// ... continue to initialize ...
return self;

または、元のクラスの新しいサブクラスを動的に生成し、その新しいクラスの新しいインスタンスを割り当てる場合もあります。

NSString* newClassName = [NSString stringWithFormat:"%@_DynamicSubclass", NSStringFromClass([self class])];
Class newClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
// ... further configure the new class, by adding instance variables or methods ...
objc_registerClassPair(newClass);
id newSelf = [newClass alloc];
[self release];
self = newSelf;
// ... continue to initialize ...
return self;

それが何をするにしても、その動的な型に基づいて、新しいインスタンスが古いインスタンスがあった場所で使用するのに適しているという制約を満たす必要があります。

于 2012-05-28T07:03:42.120 に答える
2

self隠しメソッド引数です:

// this Objective-C
- (id) initWithString:(NSString*)str;

// gets implemented like this C function would be
- (objc_object*) Foo_initWithString(Foo* self, SEL _cmd, NSString* str);

allocこれは、最も派生したオブジェクトを保持するのに十分な大きさのメモリ ( で割り当てられる) へのポインタです。最も派生したクラスは super'sinitを呼び出し、これはその super's も呼び出すinitため、階層内の各クラスはそのコンストラクターを呼び出します。

したがって、何も変換されません — 既存のオブジェクトへのポインタにすぎません。それを返す (99.9% の確率) か、代わりに別のオブジェクトを置き換えることができます。

2 番目の隠し引数、セレクターがあることに注意してください。_cmdこの場合、セレクターは に等しくなり@selector(initWithString:)ます。デバッグ ロギングなど、現在のメソッド名が必要な場合にも使用できます。

于 2012-05-28T06:09:28.430 に答える
0

ここでは、スーパーインスタンスは派生インスタンスに割り当てられていません。self = [super init];これは、ランタイムシステムにスーパークラスメソッドセレクタテーブルのinitメソッドを探すように指示するようなものです...スーパー-initメソッド内でselfは、スーパークラスと派生クラスの両方をサポートするようなものです。Objective cでは、クラスの継承の場合、インスタンス変数のみが複製されます。メソッドは、階層内のすべてのクラスで共有されます。uがオーバーライドする場合..uは実行する必要がありself = [super init]ます; これにより、uはNSObject-initメソッドになります。-init...スーパークラスのメソッドをオーバーライドする場合は、スーパー-init...が最初に呼び出されることを確認してください。これは私が理解していることです。ありがとうございました。

于 2012-05-28T07:18:48.027 に答える