0

自分のやりたいことができるとは思えませんが、ここには自分より狡猾な人たちがいるので、とにかく聞いてみようと思いました....

クラス A があるとします。

@interface A
@property (strong) NSArray *items;
// There'll be methods and stuff too
@end

ここで、いくつかの動作面を変更するために、このクラスを置き換える必要があります。

@interface B : A
@property (strong) NSArray *items;
// There'll be methods and stuff too
@end

特に、"items" プロパティをオーバーライドして、別のものを返す必要があるためです。

これは、A に実装され、B によってオーバーライドされていない B のインスタンスで呼び出されるメソッドが「self.items」にアクセスしようとするまではうまく機能します。独自のコピーにアクセスするのではなく、B のオーバーライドされたバージョンにアクセスするため、予期しない結果が表示され、実際に私の実際のケースではアプリがクラッシュします :(

Bのプロパティの名前を変更することでこれを解決できますが、これはもはや代替品ではなく、残念です。

クラス B は、super を介してプロパティの A のバージョンにアクセスできることに注意してください。理想的には、クラス A からのプロパティへのアクセスは、A のバージョンにもアクセスします。助言がありますか?たとえば、私のゲッターでは、誰がそれを要求しているかを知る方法はありますか?

ティム

4

3 に答える 3

0

うーん、Bのプロパティを適切にオーバーライドするということは、BのすべてのアクセサがBの新しいプロパティにアクセスすることを意味します。Aの動作は変更されず、Aのアクセサは常にAの元のプロパティにアクセスします。それのサブレーザーです。

サブクラスが引き続きスーパークラスプロパティにアクセスするようにしたい場合は、それをオーバーライドすることはできません。限目。

また、プロパティ(またはプロパティへのアクセサー)をサブクラスで直接アクセスできるようにするには、そのコピーをインターフェイスで宣言する必要があることに注意してください(基本的にはプロパティを公開します)。Objective-Cには「保護されたプロパティ」などがないため、これが必要です。

最後に、タイプA、B、またはCのクラスをバッグに入れて、それらのタイプを忘れたとします。すべてがis-a関係を共有していることを知っているだけで、動的バインディング/イントロスペクションを使用して、どのクラスのメソッドが呼び出されるかを決定できます。タイプに基づいています。

于 2012-06-13T19:46:04.187 に答える
0

技術的にはやりたいことを達成できますが、恐ろしい回りくどいハックが必要です。この種のものは、自分の責任で製品コードに入れ、すべてがバラバラになったとしても同情を期待しないでください。

Bのサブクラスを作成しないでください。A単に を持つクラスにしますABいずれにせよ、そうでなければサブクラスで置き換えたであろうメソッドを実装します。を処理するために、 が適切な対応する呼び出しをitems行うことを確認してくださいB。実際、オーバーライドするすべてのメソッドのケースを作成してください。setItems:AA

次に、とCを持つクラスを作成します。何も実装しないでください。次の通常の規則に従い、戻り、少し奇妙なタスクを実行します。BAallocinit(id)

A *instance = [[C alloc] init];

優先するC転送ロジックのみを実装する場合:

@implementation C

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if([self.instanceOfB respondsToSelector:aSelector]) return self.instanceOfB;
    return self.instanceOfA.
}

@end

これで、すべての参照Aは、サブクラスではなくselfインスタンスへの参照になります。Aそれにもかかわらず、システム内に のインスタンスがあり、 の関連するインスタンスがそれに優先してサービスを提供するメッセージを取得することにより、Bから継承したかのように動作しますが、 まで望むものは何でも延期できます。AAA

Aのインスタンスのインスタンスを持つクラスを指定するCことで、デフォルトのものではなく、独自の継承ロジックを通過します。さらに、(id)適切な場所に戻り、どちらもオブジェクトであるため、これは安全な暗黙のキャストであり、コンパイラーは、C実装されていないメソッドを呼び出し続けても不平を言うことはありません。

于 2012-07-20T02:27:24.063 に答える