Как правильно переопределить метод класса в Objective-C в подклассе?

во второй главе своей книги по программированию iOS Джо Конвей описывает использование "себя" в методах класса в случае подкласса. Я понимаю эту концепцию и имею вопрос о проблеме подклассов.

фон: мы создали класс владения, чей метод класса + randomPossession выглядит следующим образом:

+(id)randomPossession
{
NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy", @"Rusty", @"Shiny", nil];
NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear", @"Spork", @"Mac", nil];

unsigned long adjectiveIndex = rand() % [randomAdjectiveList count];
unsigned long nounIndex = rand() % [randomNounList count];

NSString *randomName = [NSString stringWithFormat:@"%@ %@", [randomAdjectiveList objectAtIndex:adjectiveIndex], [randomNounList objectAtIndex:nounIndex]];

int randomValue = rand() % 100;

NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c", 
                                '0' + rand() % 10, 
                                'A' + rand() % 10, 
                                '0' + rand() % 10, 
                                'A' + rand() % 10,
                                '0' + rand() % 10];

Possession *newPossession = [[self alloc] initWithPossessionName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber];

return [newPossession autorelease];
}

Я знаю, что возвращаемое значение действительно должно иметь тип id, такой что id newPossession = ...

Я подкласс владения и создал класс BallGlove, который включал новый iVar, brandName, NSString*

Я преодолел + randomPossession в BallGlove следующим образом:

+(id)randomPossession
{
BallGlove *myGlove = [super randomPossession];

NSArray *brandNames = [NSArray arrayWithObjects:@"Rawlings", @"Mizuno", @"Wilson", nil];

unsigned long randomNameIndex = rand() % [brandNames count];

[myGlove setBrandName:[brandNames objectAtIndex:randomNameIndex]];

NSLog(@"myGlove is of type class: %@", [self class]);

return myGlove;
}

мой вопрос таков: является ли способ, которым я преодолел этот метод класса, подходящим и приемлемым сообществом (т. е. параллельным формату-init, захватив супер-реализацию в переменной, соответственно манипулируйте переменной, а затем верните ее? Мой вывод показывает, что возвращаемый объект имеет пример BallGlove однако, я был заинтересован в приемлемой реализации. Спасибо заранее.

4 ответов


технически все в порядке.

Я бы предложил альтернативу. Если у вас уже есть назначенный открытый инициализатор в базовом классе (который вы можете создать и вызвать из этого метода класса фабрики в любом случае), а затем использовать этот самый инициализатор (или даже новый из вашего подкласса) в методе класса подклассов.

Это не намного больше кода, но на мой взгляд легче следовать и в будущем. Инициализатор может пригодиться также в какой-то момент, но конечно это не решение для каждого приложения.


Да, это вполне разумный способ сделать это. Между методами класса и обычными методами нет ничего особенного - только то, что один выполняется классом, а другой-экземпляром.


в тот момент, когда вы переопределяете метод класса, вы можете решить реализовать его с помощью супер-реализации или без нее. Это полностью зависит от вас. Overiding init-это совершенно другая история, не только потому, что это метод экземпляра, но и потому, что он связан с Конвенцией/договором. Имейте в виду, что, например, не следует нарушать принцип подстановки Лискова.

ваш переопределенный метод класса отлично подходит, хотя я бы рассмотрим методы класса overiding как запах дизайна. Хотя это очень хорошо возможно в Objective-C, это не на других языках, и это по очень веской причине. Полиморфизм как понятие лучше привязан к экземплярам, которые могут использоваться в качестве заменителей друг друга, тогда как использование методов класса нарушает понятие (т. е. нет реальной подстановки). Это умно, но не necessesarily интуитивно понятный и гибкий.


Да, это приемлемо, чтобы сделать вашу инициализацию, как это. На самом деле именно так это и делается в большинстве случаев. Я имею в виду, что это причина для наследования от супер класса в первую очередь. Вы хотите в дополнение к тому, что присутствует в супер класс. Таким образом, вы вставляете код в то, что специфично для унаследованного класса, и это должно быть сделано таким образом.

Я думаю, как вы хотите BallGlove инициализированный объект также является фактором в определении унаследованного метода. Этот вопрос возникает при вызове Possession init или вызов BallGlove инит (не создавая экземпляр класса, чтобы использовать метод класса). Таким образом, это сводится к логике создания ваших объектов, т. е. как вы хорошо описываете BallGlove object - вы убедитесь, что ваш метод класса описывает его таким образом, который соответствует BallGlove критерии объекта и не становится общим