2011-01-31 11 views
0

は、私は次のプロトコルがありますプロトコルで宣言され、匿名のカテゴリで実装されている参照名義は?

@protocol MyProtocol 

@property (nonatomic, retain) NSObject *myProtocolProperty; 
-(void) myProtocolMethod; 

@end 

を、私は次のクラスがあります:私はクラス拡張を宣言してい

@interface MyClass : NSObject { 
} 

@end 

を、私はここに私のプロトコルのプロパティを再宣言するために持っているか、他の私がすることはできません私のクラスの残りの部分でそれらを実装します。

@interface()<MyProtocol> 

@property (nonatomic, retain) NSObject *myExtensionProperty; 

/* 
* This redeclaration is required or my @synthesize myProtocolProperty fails 
*/ 
@property (nonatomic, retain) NSObject *myProtocolProperty; 

- (void) myExtensionMethod; 

@end 

@implementation MyClass 

@synthesize myProtocolProperty = _myProtocolProperty; 
@synthesize myExtensionProperty = _myExtensionProperty; 

- (void) myProtocolMethod { 
} 

- (void) myExtensionMethod { 
} 

- (void) useMyConsumer { 
    [[[MyConsumer new] autorelease] consumeMyClassWithMyProtocol:self]; 
} 

@end 

MyConsumerが唯一のMyClassから呼び出されますので、彼らはパブリックAPIはありませんので、私はMyClassのはMyProtocolのメソッドを実装していることを確認するために、他のクラスを望んでいません。同様に、私はMyConsumerにMyClass内のクラス拡張を見たくはありません。

@interface MyConsumer : NSObject { 
} 

@end 

@implementation MyConsumer 

- (void) consumeMyClassWithMyProtocol: (MyClass<MyProtocol> *) myClassWithMyProtocol { 
    myClassWithMyProtocol.myProtocolProperty; // works, yay! 
    [myClassWithMyProtocol myProtocolMethod]; // works, yay! 

    myClassWithMyProtocol.myExtensionProperty; // compiler error, yay! 
    [myClassWithMyProtocol myExtensionMethod]; // compiler warning, yay! 
} 

@end 

私は個人的にMyProtocolを実装するために、私のクラスの拡張内MyProtocolのプロパティを再宣言避けることができる方法はありますか?

答えて

6

"匿名カテゴリ"と呼ばれているのは、実際にはclass extensionとして知られており、のプライベート機能を実装ファイルに宣言するために使用されます。その最後の部分は重要です。これは、他のクラスがクラス拡張に入れた宣言を見ることができないことを意味します(クラスがMyProtocolのメソッドを実装しているのを見ることができません)。これは、おそらく@synthesizeがプロパティを再宣言せずに失敗した原因です。代わりに

、あなたのクラスのインターフェイスでプロトコルにあなたの適合を宣言し、パブリックになりたいものは何でもメソッドを追加:

@interface MyClass : NSObject <MyProtocol> { 
} 

// public methods and properties go here 

@end 

あなたのインターフェイスに、プロトコルの宣言を追加した場合は、それも削除されますあなたの消費者が明示的にそれを指定する必要性。あなたの消費者の方法ではなく、次のシグネチャを持つことができます。

- (void) consumeMyClassWithMyProtocol: (MyClass *) myClassWithMyProtocol; 

EDIT:あなたが選択プライベート機能を公開する方法を探しているようですね。まず、あなたが達成しようとしているものとは異なるアーキテクチャを検討しようとします。それに続くのはむしろ不愉快な解決策であり、すべてが公的または私的であれば一般的にはより良いOOPです。

Appleは、問題のクラスに別のヘッダーファイルを用意することでこの問題を解決しています。このファイルでは、表示する必要のあるメソッドを宣言しています。だから、あなたは完全にパブリックである必要があり、すべてを公開するクラスのインタフェースを、持っているでしょう:

// MyClass.h 
@interface MyClass : NSObject { 
} 

@end 

そして、あなたは、擬似民間のもののためのカテゴリを宣言した別のヘッダー、:

// MyClass+Private.h 
#import "MyClass.h" 

@interface MyClass (Private) <MyProtocol> 
- (void)mySortaPrivateMethod; 
@end 

MyClass.mは、これら二つのファイルからすべてを実装して、まだクラス拡張を持つことができます:

// MyClass.m 
#import "MyClass.h" 
#import "MyClass+Private.h" 

@interface MyClass() 
- (void)myClassExtensionMethod; 
@end 

@implementation MyClass 
// everything can go here 
@end 

次に、あなたの消費者は、が含まれますで宣言を見ることができ、他の人は単にMyClass.hを使用します。

+0

正しい命名法を使用するように質問を編集しました。 –

+0

私の使用シナリオをよりよく説明するためのコードもいくつか追加しました。 あなたの最初の段落で言ったことはすべて真です。しかし、それはまさに私が求めている行動です。 MyConsumerにMyProtocolが実装されていることを確認するだけです。 問題は、クラス拡張でMyProtocolからプロパティを再定義する必要があるか、またはそれらを@合成できないことです。私はその再定義を避けたい。 –

+0

@Hath Borders更新された回答を参照してください。 –

関連する問題