2012-01-13 16 views
4

これはかなり複雑な継承階層なので、私には負担してください(使用している正確なケースを述べるのではなく、単純化しようとしました): -Objective-C - サブクラスのデリゲートのサブクラス

UITextFieldというサブクラスを作成して、TextFieldという独自のカスタム拡張拡張テキストフィールドを作成しています。ここで、この拡張機能を提供するために、TextFieldというメソッドのinitでは、すべてのデリゲートメソッドUITextFieldTextFieldに送信されるようにsuper.delegate = selfを設定しました。 TextFieldUITextFieldDelegateプロトコルを実装し、これらのデリゲートメソッドを受信して​​何か面白いことをします。

しかし、次に、TextFieldには代理人がいるようにしたいと思います。だからTextFieldDelegateという新しいプロトコルを作成します(UI -prefixがないことに注意してください)。TextFieldには対応するプロパティを持つid<TextFieldDelegate> __weak delegateのivar id<TextFieldDelegate> __weak delegateが与えられ、他のクラスはTextFieldから代理メソッドを受け取ることができます。

私はまだこれほど複雑すぎるものは何もしていないので、あなたはまだ私と一緒にいたいと思います。しかし今、私はTextFieldの別のカスタムサブクラスを作成し、それをPasswordTextFieldと呼ぶことにしよう(現実には、パスワード機能を実装するためにサブクラスを作成する必要はないだろうが、かなり洗練された実装があると仮定しよう。それはこれを必要とするだろう)。

PasswordTextFieldTextFieldのようにデリゲートプロパティがある)が、デリゲートメソッドの拡張セットを送信できるようにしたいとしましょう。たとえば、パスワードが必要なレベルの複雑度に達すると送信されるメソッドpasswordIsSecureを送ることができます。今度は通常のTextFieldで見つからないこの動作以来、私はPasswordTextFieldの新しいデリゲートメソッドを定義するPasswordTextFieldDelegate <TextFieldDelegate>を作成し、TextFieldによって送信されたすべてのデリゲートメソッドを継承します。

問題は次のとおりです。PasswordTextFieldでこれを実装するにはどうすればよいですか?動作しないもの:

継承

TextFieldのデリゲートだけTextFieldDelegateなくPasswordTextFieldDelegateに準拠しているので、私は単純に、TextFieldからデリゲートを継承することはできませんので、私はので[delegate passwordIsSecure]のようなメソッドを送信することはできませんTextFieldDelegateにはそのような方法はありません。

私は、デリゲートと呼ばれるPasswordTextFieldでIVARを宣言試みることができるが、コンパイラはもちろん、スーパークラスでデリゲートと呼ばれるIVARがすでに存在するため、これが重複宣言であると文句を言いますので、このIVAR

のオーバーライドいずれも*動作しません。変更

スーパー

私はTextFieldクラスに戻って実装するデリゲートを再定義することができ、両方のTextFieldDelegatePasswordTextFieldDelegateが、これは厄介なようで、それは、PasswordTextFieldDelegateメソッドを送信できることTextFieldを伝えているのもちろん、それはできません!

私はこの本を試したことはありません。なぜなら、本の中のすべての分かりやすいコーディング規則を破るように思えるからです。

要約すると、クラスのサブクラスがスーパークラスのデリゲートのサブデリゲートであり、このすべてがうまく収まるような独自のデリゲートを持つようにするには、何らかの方法が必要です。それを把握していない!何か案は?

は(*側の問題として、私は PasswordTextFieldは、「複製」IVARという名前のデリゲートを宣言する際、コンパイラは文句理由を理解していないが、 TextFieldはおそらく UITextFieldの複製であるIVARという名前のデリゲートを宣言したときに文句はありません

+0

は暗闇の中でちょうど打撃を受けているかもしれませんが、id として代理人の@propertyを再宣言して独自の合成をしても役に立ちませんか?私はそれが動作すると思います。それはしばらくしてから試してみてください – govi

答えて

1

UITextFieldデリゲートivarはデリゲートではなく、_delegateという名前です。それで、あなたはなぜTextFieldでそれを宣言するのか、PasswordTextFieldでは宣言しないのですか?

あなたの代理人の継承に関する問題です。私はObjectiveCがあなたが望むものをサポートしているかどうか分かりません。

「<TextFieldDelegate>」の代わりに、「id」という代理人を入力してください。次に、setDelegateをオーバーライドし、デリゲートがconformsToProtocolで確実に渡されるようにします。ただし、ここでコンパイル時間のチェックを忘れ、conformsToProtocolのランタイムチェックしか持たない

+0

_delegateの動作を明確にしてくれてありがとう。 idを型として設定することを検討しました - 可能な解決策のリストに含めるのを忘れましたが、コンパイル時のチェックが失われると言っているので、より良い解決策があると思っていましたか? –

+0

あなたは両方の世界のベストを持つことはできません(私はあなたができるとは思えません....多分いくつかの言語がこれより優れています).....私はJavaから来て、最初は。しかし、Objective-CはJavaよりもはるかに柔軟性があり、私はこれらの小さな癖で生きていくことができ、この言語の他のすべての偉大さを楽しむことができます。しかし、私は実際に何かタイプを与えることができない場合、私は 'ID'を使用します。 – bandejapaisa

+0

私はコードの例を得ることができますか? –

1

だから、そこに! ...作品と同様に、コンパイル時の警告を持って管理して..

SimpleParent.h

@protocol Parentprotocol <NSObject> 

@end 

@interface SimpleParent : NSObject { 
    id<Parentprotocol> obj; 
} 

@property (retain) id<Parentprotocol> obj; 

@end 

SimpleParent.m

#import "SimpleParent.h" 

@implementation SimpleParent 
@synthesize obj; 

@end 

SimpleChild.h

#import <Foundation/Foundation.h> 
#import "SimpleParent.h" 

@protocol SimpleChildProtocol <Parentprotocol> 


@end 

@interface SimpleChild : NSObject 

@property (assign) id<SimpleChildProtocol> obj; 

@end 

SimpleChild.m

#import "SimpleChild.h" 

@implementation SimpleChild 
@synthesize obj; 

@end 
+1

これは、SimpleChildがSimpleParentから継承する必要があるまで機能します。継承はクラスとプロトコルの両方から同時に機能するように、それを動作させる方法はありますか? – jowie

1

私はポイントを見逃している場合は私を許してくださいが、あなたの3つの異なる継承レベルは、それぞれの代理人とは異なる要件を持っているようですが、各代理人は別のプロトコルそれで、それぞれのレベルのデリゲートを異なる名前のivarとして保持し、別の参照として保持する解決策でしょうか?

たとえば、基本クラスのdelegateがあります。これは、最初に継承したサブクラスに割り当てられます。これにはlevel1delegateという独自の代理人があり、次のレベルの下には代理人のlevel2delegateという代理人がいます。もちろん、そのオブジェクトが3つのプロトコルすべてに準拠していれば、これらの3つを同じオブジェクトに設定することもできます。

基本的に、デリゲートは「デリゲート」と呼ばれなければならないというルールはないので、それを壊さないように分かち書きしないでください。

+0

彼はあなたがこれを行うことを可能にする他の言語に慣れていると思います。例えば、Javaでは、インスタンス変数を特定のインターフェース(すなわちプロトコル)に宣言することができ、サブクラスでは、インスタンス変数をより特殊化されたタイプ(すなわちインターフェースの拡張子)に再定義することができます。しかし、Javaは強く静的に型付けされています – bandejapaisa

+0

はい、Objective-Cで開発する前に私はJava開発者でした! –

関連する問題