2

通常、init または initWith... メソッドを定義し、次のように便利なコンストラクター内で呼び出します。

@implementation MyClass1 : NSObject
@synthesize n, s;

-(id)init
{
    self = [super init];
    if (self) {
        self.n = 1;
    }
    return self;
}

-(id)initWithString:(NSString *)s
{
    self = [self init];
    if (self) {
        self.s = s;
    }
    return self;
}

+(id)myClass
{
    return [[self alloc] init];
}

+(id)myClassWithString:(NSString *)s
{
    return [[self alloc] initWithString:s];
}
@end

しかし、init または initWith... メソッドを次のように定義しなくても、便利なコンストラクターを定義することは可能だと思います。

@implementation MyClass2
@synthesize n, s;

+(id)myClass
{
    MyClass2 *obj = [[self alloc] init];
    obj.n = 1;
    return obj;
}

+(id)myClassWithString:(NSString *)s
{
    MyClass2 *obj = [self myClass];
    obj.s = s;
    return obj;
}

@end

init メソッドを定義せずに便利なコンストラクターを定義するのは悪い習慣ですか?
悪い習慣である場合、その欠点や問題点を教えていただけますか?

4

3 に答える 3

1

それが実際に悪い習慣であるかどうかはわかりません。通常、便利なコンストラクターを作成すると、次のようになります。

+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;
{
    FSClub *club = [[FSClub alloc] init];
    if (club)
    {
        club.identifier = [element integerValueWithPath:@"id"];
        club.name       = [element valueWithPath:@"naam"];
        club.referer    = [element URLWithPath:@"referer"];
    }
    return club;
}

コードは、「通常の」初期化コンストラクターのように、メモリの問題 (初期化の失敗) の可能性を考慮しています。初期化が成功した場合にのみ、値が設定されます。

インターフェイス ファイルは次のように定義されます。

@interface FSClub : NSObject

@property (nonatomic, assign, readonly) NSInteger identifier;
@property (nonatomic, copy, readonly)   NSURL    *referer;
@property (nonatomic, copy, readonly)   NSString *name;

+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;

@end

プロパティは読み取り専用であることに注意してください。私は不変オブジェクトを作成することを好みます。スレッド化されたコードなどで扱いやすいからです。この状況でプロパティを設定する唯一の方法は、便利なコンストラクターを使用することです。

便利なコンストラクターを作成するとき、これらは通常、オブジェクトをインスタンス化するために使用する唯一のメソッドです。つまり、この-initメソッドはほとんどの場合使用されません。また、使用しない場合でも、多くの初期化子を作成すると、多くの開発者の時間がかかります。使用しないメソッドは作成しません。

フレームワークの一部としてコードを作成する場合 (知らない多くの人と共有するコード)、そのような状況では、便利なコンストラクターとすべての通常のコンストラクターの両方を書きたいと思うかもしれません。コードが人々自身のプロジェクトでどのように使用されるかを確認してください。たとえば、オブジェクトが自動解放プールに追加されるため、狭いループでコンビニエンス コンストラクターを使用して多数のオブジェクトを作成すると、パフォーマンスが低下する可能性があります。これは ARC シナリオにも当てはまると思います。このような状況では、「通常の」コンストラクターを使用してオブジェクトを作成するオプションがある場合があります。

于 2012-08-31T08:04:18.743 に答える
0
//I think it is BAD. First of all, you confused CLASS and OBJECT, you get an object like this

//    [[CLASSNAME alloc] init];

//not like this: 

//    [[OBJECT alloc] init];

//so, what you want to do shall be like this:

//    +(id)myClass
//    {
//        MyClass2 *obj = [[[self class] alloc] init];
//        obj.n = 1;
//        return obj;
//    }

@W'rkncacnterのおかげで、何よりも無視してください。

ただし、ここでは自動解放せずに自分が所有するオブジェクトを返しています。これはお勧めできません。

多分あなたが本当に欲しいのはファクトリーメソッドのようなものですか?

+(id)myObjectWithString:(NSString *)string
{
    MyClass2 *obj = [[[MyClass2 alloc] init] autorelease];
    obj.s = string;
    return obj;
}
于 2012-08-31T07:46:08.663 に答える
0

あなたがしたようにそれを行うとMyClass1、指定された初期化子を定義するのが簡単になります。Apple はこれらを推奨しています。コードの繰り返しを減らすのに役立ちます。

于 2012-08-31T08:36:10.333 に答える