0

クラスに次の ivar/プロパティがあるとします。

@property (nonatomic, copy)   NSString *itemName;
@property (nonatomic, copy)   NSString *serialNumber;
@property (nonatomic) int     valueInDollars;
@property  NSDate *dateCreated; 

1) このクラスの ivar を初期化する 1 つの方法は次のとおりです。

// Designated initializer of this class 
-(id) initWithItemName: (NSString*) name
      valueInDollars:(int)value
      serialNumber:(NSString *)sNumber
{

    // Call the superclass's designated initializer
    self = [super init];

    if(self)
    {
        // Init properties
        self.itemName =  name;          
        self.serialNumber = sNumber;      
        self.valueInDollars = value;       
        dateCreated = [[NSDate alloc] init];  
    }

    // Return the address of the newly initialized object
    return self;
}

2)私が考えているもう1つの方法は、このクラスを初期化することです。たとえば、次のように書くことです:

-(id) init
{
 self = [super init];

    if(self)
    {
     // basically do nothing
    }

return self;

}

そして、クラスを使用して必要に応じて初期化を行うユーザーに任せます。たとえば、

MyClass *object = [[MyClass alloc] init];

object.dateCreated = [[NSDate alloc] init];
[object.dateCreated someMethod];
object.itemName = "Hello";
object.someProperty = [[SomeClass alloc] init];

上記のことは、一部のプロパティ(上記のように)をalloc/init使用する前に呼び出す必要があるということですよね?ユーザーがそうするのを忘れた場合、せいぜいアプリが期待どおりに動作しませんよね? (メッセージを nil に送信できるため、クラッシュしません)。ここに書いたことは、この初期化方法の唯一の問題のようです。あなたの意見は何ですか?

ps。ここでも許可されています:http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/Initialization/Initialization.html

pps。ARCが使用されていると仮定します。

多くの返信をありがとう、しかし基本的に私はソリューション 2 で考えられる問題に興味がありましたか?

4

6 に答える 6

1

同じステップで割り当てと初期化を組み合わせ、初期化の詳細を隠すために、init メソッドを呼び出すファクトリ メソッドを作成することをお勧めします。

@interface CCAttachment()
@property (readwrite, strong, nonatomic) NSString *urlString;
@property (readwrite, strong, nonatomic) NSString *baseURLString;
@property (readwrite, strong, nonatomic) NSData *data;
@property (readwrite, strong, nonatomic) id object;
@property (readwrite, strong, nonatomic) AFHTTPClient *client;
@end

@implementation CCAttachment
//Init method
- (id)initWithURLString:(NSString *)aURLString baseURLString:(NSString *)aBaseURLString
{
    self = [super init];
    if (self)
    {
        self.urlString = aURLString;
        self.baseURLString = aBaseURLString;
    }
    return self;
}
//Factory method
+ (instancetype)attachmentWithURLString:(NSString *)aURLString baseURLString:(NSString *)aBaseURLString
{
    return [[self alloc] initWithURLString:aURLString baseURLString:aBaseURLString];
}

@end

インスタンスを作成するためのより統一されたインターフェースを提供します。たとえば、後で上記のオブジェクトを nsmanagedobject に変換する場合は、同じファクトリ メソッドを保持し、その実装のみを変更します。

+ (instancetype)attachmentWithURLString:(NSString *)aURLString baseURLString:(NSString *)aBaseURLString
{
    CCAttachment *result = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass(self.class) inManagedObjectContext:MOC];
    result.urlString = aURLString;
    result.baseURLString = aBaseURLString;
    return result;
}

http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/ClassFactoryMethods/ClassFactoryMethods.html

于 2013-08-07T10:45:20.083 に答える
1

リンク先のドキュメントで答えが見つかると思います:

オブジェクトを初期化するために追加のデータを必要としないサブクラスでは、init をオーバーライドしても問題ありません。しかし、多くの場合、初期化はオブジェクトを適切な初期状態に設定するために外部データに依存します。

したがって、変数が適切な値に初期化されていない場合にクラスが適切な状態にない場合は、使用する必要があります

- (id)initWithItemName:(NSString*)name valueInDollars:(int)value serialNumber:(NSString *)sNumber

次に、init指定された初期化子をデフォルト値で呼び出すか、妥当なデフォルト値がない場合はSO でinit説明されているように使用を許可しません

于 2013-08-07T08:31:17.927 に答える
0

あらゆる種類のクラッシュを防ぐために、ivar を自分で初期化するようにしてください。最初のアプローチは、ユーザーがすべてのパラメーターを入力するように制限し、安全です。2番目のアプローチは、あなたが言及したクラッシュを引き起こす可能性がありますが、2番目のアプローチで自分で変数を初期化すれば安全です。

-(id) init
{
 self = [super init];

    if(self)
    {
     itemName = @"";
    serialNumber = @"";
    valueindollars = -1;
    dateCreated = nil;//Better than garbage
    }

return self;

}

適切なプログラミング手法として、ガベージ値へのアクセスを避けるために、オブジェクトを nil に初期化する必要があります。

于 2013-08-07T08:32:06.340 に答える
0

オブジェクト指向設計の基本に慣れておく必要があります。

一般に、クラスのインスタンスは、作成後に明確に定義された不変条件を満たさなければなりません。つまり、インスタンス (すべての ivar を含む) は、初期化された後、特定の論理的に正しい状態になる必要があります。

また、メッセージに応答した後も、インスタンスがその不変条件を満たさなければならない必要があります。この状態は、メッセージに応答する前とは異なる場合がありますが、まだ妥当な状態にある必要があります。

2 番目の設計では、ユーザーはプロパティを通じていつでも任意の ivar を設定および読み取ることができます。ここで、インスタンスが、クラスでメソッドとして定義した他のメッセージにも応答するとします。

そして、その質問に答えてください。あなたのクラスのインスタンスが常に不変条件を満たす状態にあり、したがって常に明確かつ定義された方法でメッセージに応答できることが保証されていますか?

2 番目のアプローチでは、これは、クラスが 4 つの ivarのコンテナーとして機能するだけで、実質的に他の責任を持たない場合にのみ発生することに気付くでしょう。では、そもそもクラスの目的は何なのかを尋ねる必要があります。;)

于 2013-08-07T09:27:59.733 に答える