2

クラスと、呼び出されBasicDateた のサブクラスがあるとします。クラス間の違いは、月-日-年と日-月-年です。同じクラスのメソッドを別の方法で出力する方がおそらく良いと思いますが、それはこの質問のポイントではありません。BasicDateEuroDate

BasicDate以下がありますinit method

-(id)initWithMonth:(int)m andDay:(int)d andYear:(int)y {
    if(self = [super init]) { /*initialize*/ } return self;
}

マッチングfactory methodは次のようになります。

+(BasicDate)dateWithMonth:(int)m andDay:(int)d andYear:(int)y {
    return [[BasicDate alloc] initWithMonth: m andDay: d andYear: y];
}

しかし、私のサブクラスの場合、次のようなものEuroDateを使用しfactory methodます:

+(EuroDate)dateWithDay:(int)d andMonth:(int)m andYear:(int)y {
    return [[EuroDate alloc] initWithDay: d andMonth: m andYear: y];
} //we can assume that EuroDate includes this init method...

これで問題ありません。ここで、両方のクラスに独自の があると仮定します。description methodこれはに対して出力MMDDYYYYされますBasicDateDDMMYYYYEuroDate. これでもまだ大丈夫です。

しかし、私がこれを行うと:

EuroDate today = [EuroDate dateWithMonth:10 andDay:18 andYear:2013];

これにより、継承したBasicDateファクトリ メソッドが呼び出されます。問題は、のファクトリ メソッドが EuroDateどのように見えるか覚えているかということです。BasicDatereturn [[BasicDate alloc] ...]

したがって、 として保存したいにもかかわらずtodayにポリモーフするため、メソッドを呼び出すと、ではなく が出力されます。BasicDateEuroDatedescription1018201318102013

私が見つけたこの問題には2つの解決策があります。

解決策 1:BasicDateのファクトリ メソッドを変更します。ではなくreturn [[BasicDate alloc] ...、代わりにこれを行うことができますこれは機能し、またはのサブクラスreturn [[[self class] alloc] ...] に対してこのメ​​ソッドを使用できるようにし、正しいオブジェクトタイプを返します。BasicDateBasicDate

解決策 2:Overrideファクトリ メソッド。オーバーライドして例外をスローするか、オーバーライドして do にするかreturn [[EuroDate alloc] ...]。オーバーライドの問題は、すべてのサブクラスのすべてのファクトリ メソッドをオーバーライドする必要があることです。

どちらが良いですか?私が見逃している可能性のある2つの解決策の欠点は何ですか? Objective C でこの問題を処理する標準的な方法は何ですか?

4

1 に答える 1

3

通常、[[[self class] alloc] init...]in factory メソッドを使用して、正しいクラスのインスタンスが確実に作成されるようにする必要があります。はプロパティではないことに注意してくださいclass(実際、「クラス プロパティ」などは存在しません)。そのため、ドット構文の使用は不適切です。

編集

@ArkadiuszHolko (および Rob、ありがとう) が指摘したように、サブクラスの型の柔軟性を維持しながら強力な型指定の利点を得るために、戻り値ではinstancetypeなく使用する必要があります。idところで、Apple の命名規則では、メソッド名に「and」という単語を使用しないように提案されています。したがって、次のように便利なメソッドを書き直すことを検討してください。

+ (instancetype)dateWithMonth:(int)month day:(int)day year:(int)year
{
    return [[self alloc] initWithMonth:month day:day year:year];
}
于 2013-10-18T14:40:32.733 に答える