3

カテゴリを使用してメソッドをオーバーライドすることは推奨されない方法であることを理解しています。それにもかかわらず、これを行うコードを処理する必要があります。次のコードを実行したとき、カテゴリ メソッドが両方のケースで呼び出されたことに最初は驚きましたが、リンカーが特定のシンボルのリンク時にどのように決定を下さなければならないかを考えると、気分が良くなりました。

私の質問: 私が作成したもの以外に他のカテゴリが使用されていないと仮定すると、ヘッダーがどこかからインポートされている限り、私のカテゴリの実装は常に呼び出されるロジックであることが保証されますか?

someObject.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end

someObject.m

#import "SomeObject.h"

@implementation SomeObject

- (void)doSomething
{
    NSLog(@"Original");
}

@end

someObject+Cat.h

#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end

someObject+Cat.m

#import "SomeObject+Cat.h"

@implementation SomeObject (SomeObject)

- (void)doSomething
{
    NSLog(@"New!");
}

@end

someObjectUser.h

#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end

someObjectUser.m

#import "SomeObjectUser.h"

#import "SomeObject.h"

@implementation SomeObjectUser

- (void)useSomeObject
{
    [[SomeObject new] doSomething];
}

@end

Test.m

- (void)testExample
{
    [[SomeObject new] doSomething];
    [[SomeObjectUser new] useSomeObject];
}

結果

2013-02-28 11:32:37.417 CategoryExample[933:907] New!
2013-02-28 11:32:37.419 CategoryExample[933:907] New!
4

2 に答える 2

5

私が作成したもの以外に他のカテゴリが使用されていないと仮定すると、ヘッダーがどこかからインポートされている限り、私のカテゴリの実装が常に呼び出されるロジックになることが保証されますか?

カテゴリヘッダーをインポートするかどうかはまったく問題ではありません。ヘッダーはコンパイラの情報です。カテゴリは実行時にクラスに追加され、特定のメソッドに使用される実装の選択は実行時に行われます。さらに重要なことには...

Objective-Cプログラミングガイドから:

カテゴリで宣言されたメソッドの名前が元のクラスのメソッド、または同じクラス (またはスーパークラス) の別のカテゴリのメソッドと同じである場合、どのメソッド実装が使用されているかについての動作は未定義です。ランタイム。独自のクラスでカテゴリを使用している場合、これが問題になる可能性は低くなりますが、カテゴリを使用して標準の Cocoa または Cocoa Touch クラスにメソッドを追加する場合に問題が発生する可能性があります。

(私のものを強調してください。)

undefinedという言葉の使用を考えると、質問に対する答えはノーであると言えます。カテゴリ内の既存のメソッドを再実装するときにどの実装が使用されるかについての保証はありません。実際には、クラスが独自のものである場合、カテゴリのメソッドが選択される可能性が高く、特定のバージョンのコンパイラとランタイムのテストで機能する場合、信頼できると信じています。

于 2013-02-28T16:58:40.393 に答える
0

更新

以下にリンクされているSOの回答では、Objective-Cカテゴリのドキュメントを指すリンクが無効になっています。ここに最新バージョンがあります。名前の競合を回避するセクションがあります。


はい、このSOの回答によると、(見つけたらAppleの公式リンクを投稿します)。

いくつかの警告があります。元のメソッドにはアクセスできませんが、いつでも にアクセスできsuperます。(同じクラスの) 別のカテゴリで宣言されたメソッドがオーバーライドされるという保証はありません。

于 2013-02-28T16:57:35.253 に答える