Object-Cにおけるカスタムクラスの実装<br>プロトコル


人間(personクラス)、アドレス帳クラス(myBookクラス)、スコアクラス(Fractionクラス)などのカスタムクラスのcopyメソッドを使用しようとすると、
 myBook = [myBook mutableCopy];
 person = [Person copy];
などの同様の操作では、次のような異常なエラーメッセージが表示されます.
-[Fraction copyWithZone:]:unrecognized selector sent to instance 0 x 7 fabb 8414380このエラーは、カスタムクラスに対して、独自のクラスを使用してレプリケーションを実行するには、プロトコルに従って1、2つの方法を実装する必要があります.
次に、カスタムスコアクラス(Fractionクラス)にcopyメソッドを追加する方法を示します.注意:ここで説明するレプリケーションポリシーのテクニックは、自分で定義したクラスに適しています.これらのクラスが任意のFoundationクラスのサブクラスである場合、より複雑なレプリケーションポリシーを実装する必要がある場合があります.スーパークラスが独自のレプリケーションポリシーを実装している可能性があるという事実を考慮する必要があります.
プロトコルを実装する場合、クラスはcopyWithZone:copyメッセージに応答する方法を実装する必要があります.(このcopyメッセージはnilパラメータ付きのcopyWithZone:メッセージをクラスに送信するだけです).ただし、可変レプリカと可変レプリカを区別する場合は、copyWithZone:可変レプリカを返し、mutableCopyWithZone:可変レプリカを返します.オブジェクトの可変コピーを生成するには、コピーされたオブジェクト自体も可変である必要はありません(逆も同様です).可変コピーを生成する可変コピーは合理的です(たとえば、文字列オブジェクト).
フランクフルトでhファイルには次のようなものがあります.(FractionはNSObjectのサブクラスであり、NSCopyingプロトコルに準拠しています)
#import <Foundation/Foundation.h>

@interface Fraction : NSObject<NSCopying>
{
    int a, b;
}

@property int a, b;

-(void)setTo:(int) a over: (int) b;
-(void)print;

@end

実装ファイルmでは、新しいメソッドに次の定義を追加します.
#import "Fraction.h"

@implementation Fraction

@synthesize a,b;

-(void)setTo:(int) aa over: (int) bb
{
    a = aa;
    b = bb;
}

-(void)print
{
    NSLog(@"%i/%i",a, b);
}

// NSCopying , copy 
-(id)copyWithZone:(NSZone *)zone
{
    Fraction *newFract = [[Fraction allocWithZone:zone] init];
    
    [newFract setTo:a over:b];
    
    return newFract;
}

@end

ファイルmにおける上記クラスに対するテストコードは以下の通りである.
#import <Foundation/Foundation.h>
#import "Fraction.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Fraction *f1 = [[Fraction alloc] init];
        Fraction *f2;
        
        [f1 setTo:2 over:5];
        
        f2 = [f1 copy]; 
        
        [f2 setTo:1 over:3];
        
        [f1 print];
        [f2 print];
        
        [f1 release];
        [f2 release];
        
    }
    return 0;
}

これにより、カスタムクラスFractionクラスのコピーが実現され、次のように実行されます.
2/5
プログラムの1/3 f 1というFractionオブジェクトを作成し、2/5に設定.次に、コピーを生成するためにcopyメソッドを呼び出し、copyメソッドはオブジェクトにcopyWithZone:メッセージを送信します.このメソッドは新しいFractionを生成し、f 1の値をコピーし、結果を返します.main関数に戻り、この結果をf 2に割り当てる.次に、f 2の値をスコア1/3に設定し、これらの操作が元のスコアf 1に影響を及ぼさないことを検証する.
クラスがサブクラスを生成できる場合は、copyWithZone:メソッドが継承されます.この場合、このメソッドのプログラム行は次のとおりです.
 // 
    Fraction *newFract = [[Fraction allocWithZone:zone] init];

以下に変更する必要があります.
// , 
    Fraction *newFract = [[[self class] allocWithZone:zone] init];

これにより、クラスから新しいオブジェクトを割り当てることができ、そのクラスのcopyが受信している(例えば、NewFractionというサブクラスが生成された場合、Fractionオブジェクトではなく継承メソッドに新しいNewFractionオブジェクトが割り当てられていることを確認する必要がある).
クラスのcopyWithZone:メソッドを記述し、クラスのスーパークラスもプロトコルを実装している場合は、継承されたインスタンス変数をコピーするためにスーパークラスのcopyメソッドを呼び出し、その後、クラスに追加したい追加のインスタンス変数(存在する場合)をコピーするために独自のコードを追加する必要があります.
クラスの他のユーザーに通知するために、クラスで浅いレプリケーションまたは深いレプリケーションを実行するかどうかを決定し、ドキュメントを作成する必要があります.