Как правильно переопределить метод класса в Objective-C в подклассе? - PullRequest
10 голосов
/ 28 декабря 2011

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

Справочная информация: Мы создали класс Possession, метод класса + 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 = ...

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

I overdord+ 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 ]

3 голосов
/ 28 декабря 2011

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

3 голосов
/ 28 декабря 2011

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

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

1 голос
/ 28 декабря 2011

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

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

Кроме того, не имеет значения, если вы возвращаете тип Possession в своем суперклассе, поскольку id может указывать на объект любого типа класса

0 голосов
/ 28 декабря 2011

Это технически нормально.

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

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

...