4

私はこれを学び始めたばかりなので、これがまだ理解できない明らかな解決策がある場合は申し訳ありません。

私はこれらの2つのクラスを持っています:

@implementation Person
-(void)saySomething:(NSString*) something {
    NSLog(@"%@",something);
}
-(void)yellSomething:(NSString*) something {
    [self saySomething:[something uppercaseString]];
}
@end

@implementation ShoutingPerson : Person

-(void)saySomething:(NSString*)something {
    [super yellSomething:something];
}

@end

saySomething常に子孫クラスで呼び出されるため、これにより循環参照呼び出しが発生します。

子孫クラスではなくクラスでメソッドをyellSomething呼び出すにはどうすればよいですか?saySomethingPerson

4

2 に答える 2

10

あなたはそうしない。これが、Objective-C での継承の仕組みです。代わりに、のデフォルト実装が-yellSomething:単に を呼び出すことを基本クラスに文書化する必要があります-saySomething:。その場合、スタック トレースを台無しにしないことがサブクラスの責任になります。

何を何を呼び出すかを本当に変更できるようにしたい場合は、基本クラスに 3 番目のメソッドを用意します。

-vocalizeSomething: (NSString *)what loudly: (BOOL)loudly;

言葉を発する方です。との両方が-saySomething:-yellSomething:互いに呼び出すのではなく、直接呼び出します。その後、サブクラスはいずれかのメソッドを安全にオーバーライドして他方を呼び出すかvocalizeSomething:loudly:、無限ループを作成せずに呼び出すことができます。

于 2012-12-02T16:07:29.937 に答える
6

Jonathan が言うように、これは可能な限り避けるべきです。この機能を必要とするのは、設計が悪いだけです。基本クラスがサブクラス化されることを意図している場合、そのドキュメントには、どのメソッドオーバーライドする必要があり、どのメソッドをオーバーライドできるかを詳しく説明する必要があります。このような問題を回避するために、他のものはオーバーライドしないでください。

そうは言っても、必要な非常に珍しい状況にある場合 (おそらく、リファクタリングできないサードパーティのコードで作業している場合) は可能です。しかし、それはきれいではありません。and を指すstruct objc_superのインスタンスを構築した後、objc_msgSendSuperまたはobjc_msgSendSuper_stretを手動で呼び出す必要があります。selfYourBaseClass

C++ から来た場合、デフォルトの動作は同じであることに注意してSomeFunction()ください。基本クラスから呼び出し、それが仮想メソッドである場合、サブクラスのオーバーライドが実行されます。クラスを明示的に綴るには、呼び出しの前にプレフィックスを付ける必要がありますMyBaseClass::SomeFunction()。Objective-C にはこれに直接相当するものはありません。

于 2012-12-02T18:00:35.353 に答える