0

私は最近、Objective-C でプロトコルを使用する方法を (Apple の公式ガイドを使用して) 学んでいますが、矛盾しているように思われるものを理解するのに苦労しています。ドキュメントには、次のように記載されています-

プロパティに必要なプロトコル準拠を指定すると、基本的なプロパティ クラスの型がジェネリックであっても、プロパティをプロトコルに準拠しないオブジェクトに設定しようとすると、コンパイラの警告が表示されます。

そこで、「XYZFakeProtocol」というプロトコルと、このプロトコルに準拠しない「XYZPerson」というクラスを作成して、これをテストします。次に、次のように XYZFakeProtocol に準拠することが期待される汎用クラス変数を初期化しようとします -

id <XYZFakeProtocol> speakingPerson = [[XYZPerson alloc] init];

予想通り、XCode はエラーにフラグを立てます -

<互換性のないタイプ「XYZPerson *」の式で「__strong id XYZFakeProtocol>」を初期化しています

ただし、同じことを行っても、インスタンスを手動で割り当てて初期化するのではなく、ファクトリ メソッドを使用すると、エラーは発生しません。私が使用したコードで、ファクトリ メソッドは「person:」です。

id <XYZFakeProtocol> speakingPerson = [XYZPerson person];

エラーはフラグされず、特に問題なのは、プロトコルで指定されたメソッドを呼び出したときに、そのメソッドが実際には非準拠クラスにない場合でもコンパイラ エラーが表示されないことです。これにより、プログラムがクラッシュします。

これは Xcode の問題ですか、それともファクトリ メソッドを使用した場合の予想される正しい結果ですか。実際のアプリケーションのコーディング?

参考までに、XYZPerson オブジェクトを作成して XYZPerson 変数に代入し、その変数をジェネリック型変数に代入すると、インスタンスが を使用して作成されたかどうかに関係なく、Xcode はクラスがプロトコルに準拠していないというエラーを正しくフラグ付けします。ファクトリメソッドまたは手動で初期化 -

XYZPerson *helloPerson = [XYZPerson person];
XYZPerson *helloPerson2 = [[XYZPerson alloc] init];
id <XYZFakeProtocol> speakingPerson = helloPerson;
speakingPerson = helloPerson2;

ありがとう。

4

2 に答える 2

0

これは、XYZPerson クラスの定義方法によって異なります。personを返す場合id、タイプ チェッカーはそれを任意のオブジェクト タイプと互換性があるものとして扱います。personが返された場合instancetype、プロトコルの適合性に関するエラーが表示されます。

于 2014-06-11T21:52:43.853 に答える
0

次のように宣言したと仮定しても安全です。

+ (id)person;

それを次のように変更します。

+ (instancetype)person;

id任意の型を表すため、コンパイラは返されたオブジェクトがプロトコルを実装するかどうかを知りません。instancetypeその型のインスタンスを意味するので、コンパイラは認識します。

instancetypeは比較的新しい追加であるため、コンパイラは喜んでinitメソッドに追加します。ただし、ファクトリ メソッドに対してはそうする気はありません。

于 2014-06-11T21:52:58.247 に答える